// // EntityScriptServerLogClient.cpp // interface/src // // Created by Clement Brisset on 2/1/17. // Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include #include #include "EntityScriptServerLogClient.h" #include "ScriptMessage.h" #include "ScriptEngines.h" EntityScriptServerLogClient::EntityScriptServerLogClient() { auto nodeList = DependencyManager::get(); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::EntityServerScriptLog, PacketReceiver::makeSourcedListenerReference(this, &EntityScriptServerLogClient::handleEntityServerScriptLogPacket)); QObject::connect(nodeList.data(), &NodeList::nodeActivated, this, &EntityScriptServerLogClient::nodeActivated); QObject::connect(nodeList.data(), &NodeList::nodeKilled, this, &EntityScriptServerLogClient::nodeKilled); QObject::connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptServerLogClient::canRezChanged); } void EntityScriptServerLogClient::connectNotify(const QMetaMethod& signal) { // This needs to be delayed or "receivers()" will return completely inconsistent values QMetaObject::invokeMethod(this, "connectionsChanged", Qt::QueuedConnection); } void EntityScriptServerLogClient::disconnectNotify(const QMetaMethod& signal) { // This needs to be delayed or "receivers()" will return completely inconsistent values QMetaObject::invokeMethod(this, "connectionsChanged", Qt::QueuedConnection); } void EntityScriptServerLogClient::connectionsChanged() { auto numReceivers = receivers(SIGNAL(receivedNewLogLines(QString))); if (!_subscribed && (numReceivers > 0 || _areMessagesRequestedByScripts)) { enableToEntityServerScriptLog(DependencyManager::get()->getThisNodeCanRez()); } else if (_subscribed && (numReceivers == 0 && !_areMessagesRequestedByScripts)) { enableToEntityServerScriptLog(false); } } void EntityScriptServerLogClient::enableToEntityServerScriptLog(bool enable) { auto nodeList = DependencyManager::get(); if (auto node = nodeList->soloNodeOfType(NodeType::EntityScriptServer)) { auto packet = NLPacket::create(PacketType::EntityServerScriptLog, sizeof(bool), true); packet->writePrimitive(enable); nodeList->sendPacket(std::move(packet), *node); if (_subscribed != enable) { if (enable) { emit receivedNewLogLines("====================== Subscribed to the Entity Script Server's log ======================"); } else { emit receivedNewLogLines("==================== Unsubscribed from the Entity Script Server's log ===================="); } } _subscribed = enable; } } void EntityScriptServerLogClient::handleEntityServerScriptLogPacket(QSharedPointer message, SharedNodePointer senderNode) { QString messageText = QString::fromUtf8(message->readAll()); QJsonParseError error; QJsonDocument document = QJsonDocument::fromJson(messageText.toUtf8(), &error); if(document.isNull()) { qWarning() << "EntityScriptServerLogClient::handleEntityServerScriptLogPacket: Cannot parse JSON: " << error.errorString() << " Contents: " << messageText; return; } // Iterate through contents and emit messages if(!document.isArray()) { qWarning() << "EntityScriptServerLogClient::handleEntityServerScriptLogPacket: JSON is not an array: " << messageText; return; } auto scriptEngines = DependencyManager::get().data(); auto array = document.array(); for (int n = 0; n < array.size(); n++) { if (!array[n].isObject()) { qWarning() << "EntityScriptServerLogClient::handleEntityServerScriptLogPacket: message is not an object: " << messageText; continue; } ScriptMessage scriptMessage; if (!scriptMessage.fromJson(array[n].toObject())) { qWarning() << "EntityScriptServerLogClient::handleEntityServerScriptLogPacket: message parsing failed: " << messageText; continue; } switch (scriptMessage.getSeverity()) { case ScriptMessage::Severity::SEVERITY_INFO: emit scriptEngines->infoEntityMessage(scriptMessage.getMessage(), scriptMessage.getFileName(), scriptMessage.getLineNumber(), scriptMessage.getEntityID(), true); emit receivedNewLogLines("[ INFO {" + scriptMessage.getEntityID().toString() + "} " + scriptMessage.getFileName() + ":" + QString::number(scriptMessage.getLineNumber()) + "] " + scriptMessage.getMessage()); break; case ScriptMessage::Severity::SEVERITY_PRINT: emit scriptEngines->printedEntityMessage(scriptMessage.getMessage(), scriptMessage.getFileName(), scriptMessage.getLineNumber(), scriptMessage.getEntityID(), true); emit receivedNewLogLines("[ WARNING {" + scriptMessage.getEntityID().toString() + "} " + scriptMessage.getFileName() + ":" + QString::number(scriptMessage.getLineNumber()) + "] " + scriptMessage.getMessage()); break; case ScriptMessage::Severity::SEVERITY_WARNING: emit scriptEngines->warningEntityMessage(scriptMessage.getMessage(), scriptMessage.getFileName(), scriptMessage.getLineNumber(), scriptMessage.getEntityID(), true); emit receivedNewLogLines("[ WARNING {" + scriptMessage.getEntityID().toString() + "} " + scriptMessage.getFileName() + ":" + QString::number(scriptMessage.getLineNumber()) + "] " + scriptMessage.getMessage()); break; case ScriptMessage::Severity::SEVERITY_ERROR: emit scriptEngines->errorEntityMessage(scriptMessage.getMessage(), scriptMessage.getFileName(), scriptMessage.getLineNumber(), scriptMessage.getEntityID(), true); emit receivedNewLogLines("[ ERROR {" + scriptMessage.getEntityID().toString() + "} " + scriptMessage.getFileName() + ":" + QString::number(scriptMessage.getLineNumber()) + "] " + scriptMessage.getMessage()); break; default: break; } } } void EntityScriptServerLogClient::nodeActivated(SharedNodePointer activatedNode) { if (_subscribed && activatedNode->getType() == NodeType::EntityScriptServer) { _subscribed = false; enableToEntityServerScriptLog(DependencyManager::get()->getThisNodeCanRez()); } } void EntityScriptServerLogClient::nodeKilled(SharedNodePointer killedNode) { if (killedNode->getType() == NodeType::EntityScriptServer) { emit receivedNewLogLines("====================== Connection to the Entity Script Server lost ======================"); } } void EntityScriptServerLogClient::canRezChanged(bool canRez) { auto numReceivers = receivers(SIGNAL(receivedNewLogLines(QString))); if (numReceivers > 0) { enableToEntityServerScriptLog(canRez); } } void EntityScriptServerLogClient::requestMessagesForScriptEngines(bool areMessagesRequested) { _areMessagesRequestedByScripts = areMessagesRequested; connectionsChanged(); }