diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 18ba881573..37fd2da56f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3146,6 +3146,10 @@ void Application::loadServerlessDomain(QUrl domainURL) { tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); } + std::map namedPaths = tmpTree->getNamedPaths(); + nodeList->getDomainHandler().connectedToServerless(namedPaths); + + _fullSceneReceivedCounter++; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 2cf66911a4..63d9a3ab16 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2303,6 +2303,16 @@ bool EntityTree::readFromMap(QVariantMap& map) { _persistDataVersion = map["DataVersion"].toInt(); } + _namedPaths.clear(); + if (map.contains("Paths")) { + QVariantMap namedPathsMap = map["Paths"].toMap(); + for(QVariantMap::const_iterator iter = namedPathsMap.begin(); iter != namedPathsMap.end(); ++iter) { + QString namedPathName = iter.key(); + QString namedPathViewPoint = iter.value().toString(); + _namedPaths[namedPathName] = namedPathViewPoint; + } + } + // map will have a top-level list keyed as "Entities". This will be extracted // and iterated over. Each member of this list is converted to a QVariantMap, then // to a QScriptValue, and then to EntityItemProperties. These properties are used diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 5f69714432..791c030fc8 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -301,6 +301,8 @@ public: static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName); + std::map getNamedPaths() const { return _namedPaths; } + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -417,6 +419,8 @@ private: static std::function _removeMaterialFromOverlayOperator; bool _serverlessDomain { false }; + + std::map _namedPaths; }; #endif // hifi_EntityTree_h diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 3c24cc796c..431a2e8ad5 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -312,7 +312,17 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { _shareablePlaceName.clear(); setDomainInfo(lookupUrl, trigger); emit lookupResultsFinished(); - handlePath(DOMAIN_SPAWNING_POINT, LookupTrigger::Internal, false); + + QString path = DOMAIN_SPAWNING_POINT; + QUrlQuery queryArgs(lookupUrl); + const QString LOCATION_QUERY_KEY = "location"; + if (queryArgs.hasQueryItem(LOCATION_QUERY_KEY)) { + path = queryArgs.queryItemValue(LOCATION_QUERY_KEY); + } else { + path = DEFAULT_NAMED_PATH; + } + + handlePath(path, LookupTrigger::Internal, false); return true; } diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index c20d6d73be..cd8064c4c0 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -173,15 +173,15 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { QString previousHost = _domainURL.host(); _domainURL = domainURL; - if (domainURL.scheme() != URL_SCHEME_HIFI) { - setIsConnected(true); - } else if (previousHost != domainURL.host()) { + if (previousHost != domainURL.host()) { qCDebug(networking) << "Updated domain hostname to" << domainURL.host(); if (!domainURL.host().isEmpty()) { - // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname - qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData()); - QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&))); + if (domainURL.scheme() == URL_SCHEME_HIFI) { + // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname + qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData()); + QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&))); + } DependencyManager::get()->flagTimeForConnectionStep( LimitedNodeList::ConnectionStep::SetDomainHostname); @@ -250,6 +250,17 @@ void DomainHandler::activateICEPublicSocket() { emit completedSocketDiscovery(); } +QString DomainHandler::getViewPointFromNamedPath(QString namedPath) { + auto lookup = _namedPaths.find(namedPath); + if (lookup != _namedPaths.end()) { + return lookup->second; + } + if (namedPath == DEFAULT_NAMED_PATH) { + return DOMAIN_SPAWNING_POINT; + } + return ""; +} + void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) { for (int i = 0; i < hostInfo.addresses().size(); i++) { if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { @@ -297,6 +308,11 @@ void DomainHandler::setIsConnected(bool isConnected) { } } +void DomainHandler::connectedToServerless(std::map namedPaths) { + _namedPaths = namedPaths; + setIsConnected(true); +} + void DomainHandler::requestDomainSettings() { qCDebug(networking) << "Requesting settings from domain server"; diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index fbc60e2492..7137b8084d 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -76,6 +76,10 @@ public: void setIsConnected(bool isConnected); bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; } + void connectedToServerless(std::map namedPaths); + + QString getViewPointFromNamedPath(QString namedPath); + bool hasSettings() const { return !_settingsObject.isEmpty(); } void requestDomainSettings(); const QJsonObject& getSettingsObject() const { return _settingsObject; } @@ -200,9 +204,11 @@ private: int _checkInPacketsSinceLastReply { 0 }; QTimer _apiRefreshTimer; + + std::map _namedPaths; }; const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" }; - +const QString DEFAULT_NAMED_PATH { "/" }; #endif // hifi_DomainHandler_h diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index cb0d2e4cd5..13931be2ac 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -413,7 +413,16 @@ void NodeList::sendDomainServerCheckIn() { } void NodeList::handleDSPathQuery(const QString& newPath) { - if (_domainHandler.isSocketKnown()) { + if (_domainHandler.isServerless()) { + if (_domainHandler.isConnected()) { + auto viewpoint = _domainHandler.getViewPointFromNamedPath(newPath); + if (!newPath.isEmpty()) { + DependencyManager::get()->goToViewpointForPath(viewpoint, newPath); + } + } else { + _domainHandler.setPendingPath(newPath); + } + } else if (_domainHandler.isSocketKnown()) { // if we have a DS socket we assume it will get this packet and send if off right away sendDSPathQuery(newPath); } else { @@ -427,10 +436,17 @@ void NodeList::sendPendingDSPathQuery() { QString pendingPath = _domainHandler.getPendingPath(); if (!pendingPath.isEmpty()) { - qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; - // this is a slot triggered if we just established a network link with a DS and want to send a path query - sendDSPathQuery(_domainHandler.getPendingPath()); + if (_domainHandler.isServerless()) { + auto viewpoint = _domainHandler.getViewPointFromNamedPath(pendingPath); + if (!pendingPath.isEmpty()) { + DependencyManager::get()->goToViewpointForPath(viewpoint, pendingPath); + } + } else { + qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; + // this is a slot triggered if we just established a network link with a DS and want to send a path query + sendDSPathQuery(_domainHandler.getPendingPath()); + } // clear whatever the pending path was _domainHandler.clearPendingPath(); @@ -498,7 +514,7 @@ void NodeList::processDomainServerPathResponse(QSharedPointer m QString viewpoint = QString::fromUtf8(message->getRawMessage() + message->getPosition(), numViewpointBytes); // Hand it off to the AddressManager so it can handle it as a relative viewpoint - if (DependencyManager::get()->goToViewpointForPath(viewpoint, pathQuery)) { + if (!pathQuery.isEmpty() && DependencyManager::get()->goToViewpointForPath(viewpoint, pathQuery)) { qCDebug(networking) << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; } else { qCDebug(networking) << "Could not go to viewpoint" << viewpoint