diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 92c594df9e..6268a38ba3 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -162,11 +162,11 @@ function flyWithHydra(deltaTime) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); } - var currentOrientation = MyAvatar.orientation; + var headOrientation = MyAvatar.headOrientation; - var front = Quat.getFront(currentOrientation); - var right = Quat.getRight(currentOrientation); - var up = Quat.getUp(currentOrientation); + var front = Quat.getFront(headOrientation); + var right = Quat.getRight(headOrientation); + var up = Quat.getUp(headOrientation); var thrustFront = Vec3.multiply(front, MyAvatar.scale * THRUST_MAG_HAND_JETS * thrustJoystickPosition.y * thrustMultiplier * deltaTime); diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 519e2b61c1..7c5d1ecbcf 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1974ddd60c..dc1a843e47 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -170,6 +170,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _bytesPerSecond(0), _recentMaxPackets(0), _resetRecentMaxPacketsSoon(true), + _previousScriptLocation(), _logger(new FileLogger(this)) { // read the ApplicationInfo.ini file for Name/Version/Domain information @@ -3700,12 +3701,20 @@ void Application::loadScript(const QString& scriptName) { } void Application::loadDialog() { - // shut down and stop any existing script - QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - QString suggestedName = desktopLocation.append("/script.js"); + QString suggestedName; + + if (_previousScriptLocation.isEmpty()) { + QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + suggestedName = desktopLocation.append("/script.js"); + } else { + suggestedName = _previousScriptLocation; + } QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), suggestedName, tr("JavaScript Files (*.js)")); + if (!fileNameString.isEmpty()) { + _previousScriptLocation = fileNameString; + } loadScript(fileNameString); } diff --git a/interface/src/Application.h b/interface/src/Application.h index af77adb8fc..fcf8810378 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -484,6 +484,8 @@ private: ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; + QString _previousScriptLocation; + FileLogger* _logger; void checkVersion(); diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index dadf39f790..a4491fb707 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -51,6 +51,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const _lastHeardMicrostamp(usecTimestampNow()), _publicSocket(publicSocket), _localSocket(localSocket), + _symmetricSocket(), _activeSocket(NULL), _connectionSecret(), _bytesReceivedMovingAverage(NULL), @@ -84,6 +85,15 @@ void Node::setLocalSocket(const HifiSockAddr& localSocket) { _localSocket = localSocket; } +void Node::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { + if (_activeSocket == &_symmetricSocket) { + // if the active socket was the symmetric socket then reset it to NULL + _activeSocket = NULL; + } + + _symmetricSocket = symmetricSocket; +} + void Node::activateLocalSocket() { qDebug() << "Activating local socket for node" << *this; _activeSocket = &_localSocket; @@ -94,6 +104,11 @@ void Node::activatePublicSocket() { _activeSocket = &_publicSocket; } +void Node::activateSymmetricSocket() { + qDebug() << "Activating symmetric socket for node" << *this; + _activeSocket = &_symmetricSocket; +} + void Node::recordBytesReceived(int bytesReceived) { if (!_bytesReceivedMovingAverage) { _bytesReceivedMovingAverage = new SimpleMovingAverage(100); diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 43ec5baf81..79d75629a6 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -70,11 +70,14 @@ public: void setPublicSocket(const HifiSockAddr& publicSocket); const HifiSockAddr& getLocalSocket() const { return _localSocket; } void setLocalSocket(const HifiSockAddr& localSocket); - + const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } + void setSymmetricSocket(const HifiSockAddr& symmetricSocket); + const HifiSockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); void activateLocalSocket(); + void activateSymmetricSocket(); const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } @@ -110,6 +113,7 @@ private: quint64 _lastHeardMicrostamp; HifiSockAddr _publicSocket; HifiSockAddr _localSocket; + HifiSockAddr _symmetricSocket; HifiSockAddr* _activeSocket; QUuid _connectionSecret; SimpleMovingAverage* _bytesReceivedMovingAverage; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 761ea40d55..879377a2fd 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -294,6 +294,15 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr matchingNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray replyPacket = constructPingReplyPacket(packet); writeDatagram(replyPacket, matchingNode, senderSockAddr); + + // If we don't have a symmetric socket for this node and this socket doesn't match + // what we have for public and local then set it as the symmetric. + // This allows a server on a reachable port to communicate with nodes on symmetric NATs + if (matchingNode->getSymmetricSocket().isNull()) { + if (senderSockAddr != matchingNode->getLocalSocket() && senderSockAddr != matchingNode->getPublicSocket()) { + matchingNode->setSymmetricSocket(senderSockAddr); + } + } } break; @@ -782,7 +791,7 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) { return replyPacket; } -void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node) { +void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { // send the ping packet to the local and public sockets for this node QByteArray localPingPacket = constructPingPacket(PingType::Local); @@ -790,6 +799,11 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& QByteArray publicPingPacket = constructPingPacket(PingType::Public); writeDatagram(publicPingPacket, node, node->getPublicSocket()); + + if (!node->getSymmetricSocket().isNull()) { + QByteArray symmetricPingPacket = constructPingPacket(PingType::Symmetric); + writeDatagram(symmetricPingPacket, node, node->getSymmetricSocket()); + } } SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, @@ -860,7 +874,7 @@ void NodeList::pingInactiveNodes() { foreach (const SharedNodePointer& node, getNodeHash()) { if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPublicAndLocalSocketsForInactiveNode(node); + pingPunchForInactiveNode(node); } } } @@ -879,6 +893,9 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con sendingNode->activateLocalSocket(); } else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) { sendingNode->activatePublicSocket(); + } else if (pingType == PingType::Symmetric && !sendingNode->getActiveSocket()) { + + } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index d05d6a2fbc..34078b6a94 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -58,6 +58,7 @@ namespace PingType { const PingType_t Agnostic = 0; const PingType_t Local = 1; const PingType_t Public = 2; + const PingType_t Symmetric = 3; } class NodeList : public QObject { @@ -101,7 +102,7 @@ public: QByteArray constructPingPacket(PingType_t pingType = PingType::Agnostic); QByteArray constructPingReplyPacket(const QByteArray& pingPacket); - void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); + void pingPunchForInactiveNode(const SharedNodePointer& node); SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); SharedNodePointer sendingNodeForPacket(const QByteArray& packet);