mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 13:04:37 +02:00
Merge pull request #9625 from huffman/fix/server-script-entity-updates
Fix Server Entity Script w/ high update rate causing issues
This commit is contained in:
commit
026c68c7de
5 changed files with 106 additions and 1 deletions
|
@ -100,6 +100,52 @@ void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<Receiv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityScriptServer::handleSettings() {
|
||||||
|
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
|
auto& domainHandler = nodeList->getDomainHandler();
|
||||||
|
const QJsonObject& settingsObject = domainHandler.getSettingsObject();
|
||||||
|
|
||||||
|
static const QString ENTITY_SCRIPT_SERVER_SETTINGS_KEY = "entity_script_server";
|
||||||
|
|
||||||
|
if (!settingsObject.contains(ENTITY_SCRIPT_SERVER_SETTINGS_KEY)) {
|
||||||
|
qWarning() << "Received settings from the domain-server with no entity_script_server section.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto entityScriptServerSettings = settingsObject[ENTITY_SCRIPT_SERVER_SETTINGS_KEY].toObject();
|
||||||
|
|
||||||
|
static const QString MAX_ENTITY_PPS_OPTION = "max_total_entity_pps";
|
||||||
|
static const QString ENTITY_PPS_PER_SCRIPT = "entity_pps_per_script";
|
||||||
|
|
||||||
|
if (!entityScriptServerSettings.contains(MAX_ENTITY_PPS_OPTION) || !entityScriptServerSettings.contains(ENTITY_PPS_PER_SCRIPT)) {
|
||||||
|
qWarning() << "Received settings from the domain-server with no max_total_entity_pps or entity_pps_per_script properties.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_maxEntityPPS = std::max(0, entityScriptServerSettings[MAX_ENTITY_PPS_OPTION].toInt());
|
||||||
|
_entityPPSPerScript = std::max(0, entityScriptServerSettings[ENTITY_PPS_PER_SCRIPT].toInt());
|
||||||
|
|
||||||
|
qDebug() << QString("Received entity script server settings, Max Entity PPS: %1, Entity PPS Per Entity Script: %2")
|
||||||
|
.arg(_maxEntityPPS).arg(_entityPPSPerScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityScriptServer::updateEntityPPS() {
|
||||||
|
int numRunningScripts = _entitiesScriptEngine->getNumRunningEntityScripts();
|
||||||
|
int pps;
|
||||||
|
if (std::numeric_limits<int>::max() / _entityPPSPerScript < numRunningScripts) {
|
||||||
|
qWarning() << QString("Integer multiplaction would overflow, clamping to maxint: %1 * %2").arg(numRunningScripts).arg(_entityPPSPerScript);
|
||||||
|
pps = std::numeric_limits<int>::max();
|
||||||
|
pps = std::min(_maxEntityPPS, pps);
|
||||||
|
} else {
|
||||||
|
pps = _entityPPSPerScript * numRunningScripts;
|
||||||
|
pps = std::min(_maxEntityPPS, pps);
|
||||||
|
}
|
||||||
|
_entityEditSender.setPacketsPerSecond(pps);
|
||||||
|
qDebug() << QString("Updating entity PPS to: %1 @ %2 PPS per script = %3 PPS").arg(numRunningScripts).arg(_entityPPSPerScript).arg(pps);
|
||||||
|
}
|
||||||
|
|
||||||
void EntityScriptServer::run() {
|
void EntityScriptServer::run() {
|
||||||
// make sure we request our script once the agent connects to the domain
|
// make sure we request our script once the agent connects to the domain
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
@ -114,6 +160,9 @@ void EntityScriptServer::run() {
|
||||||
connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init);
|
connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init);
|
||||||
messagesThread->start();
|
messagesThread->start();
|
||||||
|
|
||||||
|
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
|
// 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::nodeActivated, this, &EntityScriptServer::nodeActivated);
|
||||||
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled);
|
connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled);
|
||||||
|
@ -232,7 +281,9 @@ void EntityScriptServer::resetEntitiesScriptEngine() {
|
||||||
newEngine->runInThread();
|
newEngine->runInThread();
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(newEngine.data());
|
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(newEngine.data());
|
||||||
|
|
||||||
|
disconnect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptDetailsUpdated, this, &EntityScriptServer::updateEntityPPS);
|
||||||
_entitiesScriptEngine.swap(newEngine);
|
_entitiesScriptEngine.swap(newEngine);
|
||||||
|
connect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptDetailsUpdated, this, &EntityScriptServer::updateEntityPPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <ThreadedAssignment.h>
|
#include <ThreadedAssignment.h>
|
||||||
|
|
||||||
|
static const int DEFAULT_MAX_ENTITY_PPS = 9000;
|
||||||
|
static const int DEFAULT_ENTITY_PPS_PER_SCRIPT = 900;
|
||||||
|
|
||||||
class EntityScriptServer : public ThreadedAssignment {
|
class EntityScriptServer : public ThreadedAssignment {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -42,6 +45,9 @@ private slots:
|
||||||
void handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleEntityScriptGetStatusPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleEntityScriptGetStatusPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
|
|
||||||
|
void handleSettings();
|
||||||
|
void updateEntityPPS();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void negotiateAudioFormat();
|
void negotiateAudioFormat();
|
||||||
void selectAudioFormat(const QString& selectedCodecName);
|
void selectAudioFormat(const QString& selectedCodecName);
|
||||||
|
@ -62,6 +68,9 @@ private:
|
||||||
EntityEditPacketSender _entityEditSender;
|
EntityEditPacketSender _entityEditSender;
|
||||||
EntityTreeHeadlessViewer _entityViewer;
|
EntityTreeHeadlessViewer _entityViewer;
|
||||||
|
|
||||||
|
int _maxEntityPPS { DEFAULT_MAX_ENTITY_PPS };
|
||||||
|
int _entityPPSPerScript { DEFAULT_ENTITY_PPS_PER_SCRIPT };
|
||||||
|
|
||||||
QString _selectedCodecName;
|
QString _selectedCodecName;
|
||||||
CodecPluginPointer _codec;
|
CodecPluginPointer _codec;
|
||||||
Encoder* _encoder { nullptr };
|
Encoder* _encoder { nullptr };
|
||||||
|
|
|
@ -178,7 +178,7 @@
|
||||||
{
|
{
|
||||||
"name": "maximum_user_capacity_redirect_location",
|
"name": "maximum_user_capacity_redirect_location",
|
||||||
"label": "Redirect to Location on Maximum Capacity",
|
"label": "Redirect to Location on Maximum Capacity",
|
||||||
"help": "Is there another domain, you'd like to redirect clients to when the maximum number of avatars are connected.",
|
"help": "The location to redirect users to when the maximum number of avatars are connected.",
|
||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"default": "",
|
"default": "",
|
||||||
"advanced": false
|
"advanced": false
|
||||||
|
@ -822,6 +822,29 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "entity_script_server",
|
||||||
|
"label": "Entity Script Server (ESS)",
|
||||||
|
"assignment-types": [5],
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "entity_pps_per_script",
|
||||||
|
"label": "Entity PPS per script",
|
||||||
|
"help": "The number of packets per second (PPS) that can be sent to the entity server for each server entity script. This contributes to a total overall amount.<br/>Example: 1000 PPS with 5 entites gives a total PPS of 5000 that is shared among the entity scripts. A single could use 4000 PPS, leaving 1000 for the rest, for example.",
|
||||||
|
"default": 900,
|
||||||
|
"type": "int",
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_total_entity_pps",
|
||||||
|
"label": "Maximum Total Entity PPS",
|
||||||
|
"help": "The maximum total packets per seconds (PPS) that can be sent to the entity server.<br/>Example: 5 scripts @ 1000 PPS per script = 5000 total PPS. A maximum total PPS of 4000 would cap this 5000 total PPS to 4000.",
|
||||||
|
"default": 9000,
|
||||||
|
"type": "int",
|
||||||
|
"advanced": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "avatars",
|
"name": "avatars",
|
||||||
"label": "Avatars",
|
"label": "Avatars",
|
||||||
|
|
|
@ -1393,6 +1393,16 @@ void ScriptEngine::forwardHandlerCall(const EntityItemID& entityID, const QStrin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScriptEngine::getNumRunningEntityScripts() const {
|
||||||
|
int sum = 0;
|
||||||
|
for (auto& st : _entityScripts) {
|
||||||
|
if (st.status == RUNNING) {
|
||||||
|
++sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const {
|
bool ScriptEngine::getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const {
|
||||||
auto it = _entityScripts.constFind(entityID);
|
auto it = _entityScripts.constFind(entityID);
|
||||||
if (it == _entityScripts.constEnd()) {
|
if (it == _entityScripts.constEnd()) {
|
||||||
|
@ -1456,6 +1466,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
||||||
newDetails.status = ERROR_LOADING_SCRIPT;
|
newDetails.status = ERROR_LOADING_SCRIPT;
|
||||||
newDetails.errorInfo = "Failed to load script";
|
newDetails.errorInfo = "Failed to load script";
|
||||||
_entityScripts[entityID] = newDetails;
|
_entityScripts[entityID] = newDetails;
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,6 +1478,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
||||||
newDetails.status = ERROR_RUNNING_SCRIPT;
|
newDetails.status = ERROR_RUNNING_SCRIPT;
|
||||||
newDetails.errorInfo = "Bad syntax";
|
newDetails.errorInfo = "Bad syntax";
|
||||||
_entityScripts[entityID] = newDetails;
|
_entityScripts[entityID] = newDetails;
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
return; // done processing script
|
return; // done processing script
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1497,6 +1509,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
||||||
newDetails.status = ERROR_RUNNING_SCRIPT;
|
newDetails.status = ERROR_RUNNING_SCRIPT;
|
||||||
newDetails.errorInfo = exceptionMessage;
|
newDetails.errorInfo = exceptionMessage;
|
||||||
_entityScripts[entityID] = newDetails;
|
_entityScripts[entityID] = newDetails;
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1523,6 +1536,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
||||||
newDetails.status = ERROR_RUNNING_SCRIPT;
|
newDetails.status = ERROR_RUNNING_SCRIPT;
|
||||||
newDetails.errorInfo = "Could not find constructor";
|
newDetails.errorInfo = "Could not find constructor";
|
||||||
_entityScripts[entityID] = newDetails;
|
_entityScripts[entityID] = newDetails;
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
|
|
||||||
return; // done processing script
|
return; // done processing script
|
||||||
}
|
}
|
||||||
|
@ -1544,6 +1558,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
|
||||||
newDetails.lastModified = lastModified;
|
newDetails.lastModified = lastModified;
|
||||||
newDetails.definingSandboxURL = sandboxURL;
|
newDetails.definingSandboxURL = sandboxURL;
|
||||||
_entityScripts[entityID] = newDetails;
|
_entityScripts[entityID] = newDetails;
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
|
|
||||||
if (isURL) {
|
if (isURL) {
|
||||||
setParentURL("");
|
setParentURL("");
|
||||||
|
@ -1575,6 +1590,7 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) {
|
||||||
}
|
}
|
||||||
_entityScripts.remove(entityID);
|
_entityScripts.remove(entityID);
|
||||||
stopAllTimersForEntityScript(entityID);
|
stopAllTimersForEntityScript(entityID);
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1596,6 +1612,7 @@ void ScriptEngine::unloadAllEntityScripts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_entityScripts.clear();
|
_entityScripts.clear();
|
||||||
|
emit entityScriptDetailsUpdated();
|
||||||
|
|
||||||
#ifdef DEBUG_ENGINE_STATE
|
#ifdef DEBUG_ENGINE_STATE
|
||||||
qCDebug(scriptengine) << "---- CURRENT STATE OF ENGINE: --------------------------";
|
qCDebug(scriptengine) << "---- CURRENT STATE OF ENGINE: --------------------------";
|
||||||
|
|
|
@ -199,6 +199,7 @@ public:
|
||||||
void scriptWarningMessage(const QString& message);
|
void scriptWarningMessage(const QString& message);
|
||||||
void scriptInfoMessage(const QString& message);
|
void scriptInfoMessage(const QString& message);
|
||||||
|
|
||||||
|
int getNumRunningEntityScripts() const;
|
||||||
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
|
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -222,6 +223,10 @@ signals:
|
||||||
void reloadScript(const QString& scriptName, bool isUserLoaded);
|
void reloadScript(const QString& scriptName, bool isUserLoaded);
|
||||||
void doneRunning();
|
void doneRunning();
|
||||||
|
|
||||||
|
// Emitted when an entity script is added or removed, or when the status of an entity
|
||||||
|
// script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
|
||||||
|
void entityScriptDetailsUpdated();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue