void EntityScriptServer::run() { DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT); DependencyManager::set<EntityScriptServerServices>(); // make sure we request our script once the agent connects to the domain auto nodeList = DependencyManager::get<NodeList>(); ThreadedAssignment::commonInit(ENTITY_SCRIPT_SERVER_LOGGING_NAME, NodeType::EntityScriptServer); // Setup MessagesClient auto messagesClient = DependencyManager::set<MessagesClient>(); messagesClient->startThread(); DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler(); connect(&domainHandler, &DomainHandler::settingsReceived, this, &EntityScriptServer::handleSettings); // make sure we hear about connected nodes so we can grab an ATP script if a request is pending connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &EntityScriptServer::nodeActivated); connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled); nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer }); // Setup Script Engine resetEntitiesScriptEngine(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); entityScriptingInterface->init(); _entityViewer.init(); // setup the JSON filter that asks for entities with a non-default serverScripts property QJsonObject queryJSONParameters; queryJSONParameters[EntityJSONQueryProperties::SERVER_SCRIPTS_PROPERTY] = EntityQueryFilterSymbol::NonDefault; QJsonObject queryFlags; queryFlags[EntityJSONQueryProperties::INCLUDE_ANCESTORS_PROPERTY] = true; queryFlags[EntityJSONQueryProperties::INCLUDE_DESCENDANTS_PROPERTY] = true; queryJSONParameters[EntityJSONQueryProperties::FLAGS_PROPERTY] = queryFlags; // setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter _entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree()); auto tree = _entityViewer.getTree().get(); connect(tree, &EntityTree::deletingEntity, this, &EntityScriptServer::deletingEntity, Qt::QueuedConnection); connect(tree, &EntityTree::addingEntity, this, &EntityScriptServer::addingEntity, Qt::QueuedConnection); connect(tree, &EntityTree::entityServerScriptChanging, this, &EntityScriptServer::entityServerScriptChanging, Qt::QueuedConnection); }
void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); auto nodeList = DependencyManager::get<NodeList>(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer ); _pingTimer = new QTimer(this); connect(_pingTimer, SIGNAL(timeout()), SLOT(sendPingRequests())); _pingTimer->start(PING_INTERVAL); // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") .arg(DependencyManager::get<NodeList>()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { scriptURL = QUrl(_payload); } QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(scriptURL); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); QNetworkReply* reply = networkAccessManager.get(networkRequest); QNetworkDiskCache* cache = new QNetworkDiskCache(); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); networkAccessManager.setCache(cache); qDebug() << "Downloading script at" << scriptURL.toString(); QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString scriptContents(reply->readAll()); delete reply; qDebug() << "Downloaded script:" << scriptContents; // setup an Avatar for the script to use ScriptableAvatar scriptedAvatar(&_scriptEngine); scriptedAvatar.setForceFaceTrackerConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setSkeletonModelURL(QUrl()); // give this AvatarData object to the script engine _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); auto avatarHashMap = DependencyManager::set<AvatarHashMap>(); _scriptEngine.setAvatarHashMap(avatarHashMap.data(), "AvatarList"); auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver(); packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket"); packetReceiver.registerListener(PacketType::AvatarBillboard, avatarHashMap.data(), "processAvatarBillboardPacket"); // register ourselves to the script engine _scriptEngine.registerGlobalObject("Agent", this); if (!_payload.isEmpty()) { _scriptEngine.setParentURL(_payload); } _scriptEngine.init(); // must be done before we set up the viewers _scriptEngine.registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data()); QScriptValue webSocketServerConstructorValue = _scriptEngine.newFunction(WebSocketServerClass::constructor); _scriptEngine.globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); _entityViewer.init(); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); setFinished(true); }
void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); auto nodeList = DependencyManager::get<NodeList>(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer ); // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") .arg(DependencyManager::get<NodeList>()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { scriptURL = QUrl(_payload); } QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL)); QNetworkDiskCache* cache = new QNetworkDiskCache(); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); networkAccessManager.setCache(cache); qDebug() << "Downloading script at" << scriptURL.toString(); QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString scriptContents(reply->readAll()); delete reply; qDebug() << "Downloaded script:" << scriptContents; // setup an Avatar for the script to use ScriptableAvatar scriptedAvatar(&_scriptEngine); scriptedAvatar.setForceFaceshiftConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setSkeletonModelURL(QUrl()); // give this AvatarData object to the script engine _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); _scriptEngine.setAvatarHashMap(&_avatarHashMap, "AvatarList"); // register ourselves to the script engine _scriptEngine.registerGlobalObject("Agent", this); _scriptEngine.init(); // must be done before we set up the viewers _scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance()); _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()); _entityViewer.init(); _scriptEngine.getEntityScriptingInterface()->setEntityTree(_entityViewer.getTree()); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); setFinished(true); }
ATPClientApp::ATPClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity ATP-Client"); const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); const QCommandLineOption uploadOption("T", "upload local file", "local-file-to-send"); parser.addOption(uploadOption); const QCommandLineOption authOption("u", "set usename and pass", "username:password"); parser.addOption(authOption); const QCommandLineOption outputFilenameOption("o", "output filename", "output-file-name"); parser.addOption(outputFilenameOption); const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); Q_UNREACHABLE(); } if (parser.isSet(helpOption)) { parser.showHelp(); Q_UNREACHABLE(); } _verbose = parser.isSet(verboseOutput); if (!_verbose) { QLoggingCategory::setFilterRules("qt.network.ssl.warning=false"); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false); } QStringList posArgs = parser.positionalArguments(); if (posArgs.size() != 1) { qDebug() << "give remote url argument"; parser.showHelp(); Q_UNREACHABLE(); } _url = QUrl(posArgs[0]); if (_url.scheme() != "atp") { qDebug() << "url should start with atp:"; parser.showHelp(); Q_UNREACHABLE(); } int domainPort = 40103; if (_url.port() != -1) { domainPort = _url.port(); } if (parser.isSet(outputFilenameOption)) { _localOutputFile = parser.value(outputFilenameOption); } if (parser.isSet(uploadOption)) { _localUploadFile = parser.value(uploadOption); } if (parser.isSet(authOption)) { QStringList pieces = parser.value(authOption).split(":"); if (pieces.size() != 2) { qDebug() << "-u should be followed by username:password"; parser.showHelp(); Q_UNREACHABLE(); } _username = pieces[0]; _password = pieces[1]; _waitingForLogin = true; } if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } _domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { _domainServerAddress = parser.value(domainAddressOption); } else if (!_url.host().isEmpty()) { QUrl domainURL; domainURL.setScheme("hifi"); domainURL.setHost(_url.host()); _domainServerAddress = domainURL.toString(); } DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::set<StatTracker>(); DependencyManager::set<AccountManager>([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set<AddressManager>(); DependencyManager::set<NodeList>(NodeType::Agent, _listenPort); auto accountManager = DependencyManager::get<AccountManager>(); accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get<NodeList>(); // setup a timer for domain-server check ins _domainCheckInTimer = new QTimer(nodeList.data()); connect(_domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); _domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); // start the nodeThread so its event loop is running // (must happen after the checkin timer is created with the nodelist as it's parent) nodeList->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::nodeActivated); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ if (_verbose) { qDebug() << "new keypair has been created."; } }); connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; } _waitingForLogin = false; go(); }); connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ qDebug() << "login failed."; _waitingForLogin = false; go(); }); accountManager->requestAccessToken(_username, _password); } auto assetClient = DependencyManager::set<AssetClient>(); assetClient->init(); if (_verbose) { qDebug() << "domain-server address is" << _domainServerAddress; } DependencyManager::get<AddressManager>()->handleLookupString(_domainServerAddress, false); QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); _timeoutTimer->start(TIMEOUT_MILLISECONDS); }
ACClientApp::ACClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity AC client"); const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); const QCommandLineOption authOption("u", "set usename and pass", "username:password"); parser.addOption(authOption); const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); parser.addOption(cacheSTUNOption); const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); Q_UNREACHABLE(); } if (parser.isSet(helpOption)) { parser.showHelp(); Q_UNREACHABLE(); } _verbose = parser.isSet(verboseOutput); if (!_verbose) { QLoggingCategory::setFilterRules("qt.network.ssl.warning=false"); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false); } QString domainServerAddress = "127.0.0.1:40103"; if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); } if (_verbose) { qDebug() << "domain-server address is" << domainServerAddress; } int listenPort = INVALID_PORT; if (parser.isSet(listenPortOption)) { listenPort = parser.value(listenPortOption).toInt(); } if (parser.isSet(authOption)) { QStringList pieces = parser.value(authOption).split(":"); if (pieces.size() != 2) { qDebug() << "-u should be followed by username:password"; parser.showHelp(); Q_UNREACHABLE(); } _username = pieces[0]; _password = pieces[1]; } DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); }); DependencyManager::set<AddressManager>(); DependencyManager::set<NodeList>(NodeType::Agent, listenPort); auto accountManager = DependencyManager::get<AccountManager>(); accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get<NodeList>(); // setup a timer for domain-server check ins QTimer* domainCheckInTimer = new QTimer(nodeList.data()); connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); // start the nodeThread so its event loop is running // (must happen after the checkin timer is created with the nodelist as it's parent) nodeList->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainChanged(QUrl))); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ACClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ACClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ACClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ACClientApp::nodeActivated); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ACClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ if (_verbose) { qDebug() << "new keypair has been created."; } }); connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; } }); connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ qDebug() << "login failed."; }); accountManager->requestAccessToken(_username, _password); } DependencyManager::get<AddressManager>()->handleLookupString(domainServerAddress, false); QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); connect(doTimer, &QTimer::timeout, this, &ACClientApp::timedOut); doTimer->start(4000); }