mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Merge pull request #11646 from ZappoMan/callServerEntityMethod
implement support for Entities.callEntityServerMethod()
This commit is contained in:
commit
ea38b32dea
10 changed files with 121 additions and 14 deletions
|
@ -85,6 +85,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
|||
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
||||
|
||||
static const int LOG_INTERVAL = MSECS_PER_SECOND / 10;
|
||||
auto timer = new QTimer(this);
|
||||
|
@ -231,6 +232,27 @@ void EntityScriptServer::pushLogs() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode) {
|
||||
|
||||
if (_entitiesScriptEngine && _entityViewer.getTree() && !_shuttingDown) {
|
||||
auto entityID = QUuid::fromRfc4122(receivedMessage->read(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
auto method = receivedMessage->readString();
|
||||
|
||||
quint16 paramCount;
|
||||
receivedMessage->readPrimitive(¶mCount);
|
||||
|
||||
QStringList params;
|
||||
for (int param = 0; param < paramCount; param++) {
|
||||
auto paramString = receivedMessage->readString();
|
||||
params << paramString;
|
||||
}
|
||||
|
||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EntityScriptServer::run() {
|
||||
// make sure we request our script once the agent connects to the domain
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
|
|
@ -54,6 +54,9 @@ private slots:
|
|||
|
||||
void pushLogs();
|
||||
|
||||
void handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
|
||||
|
||||
private:
|
||||
void negotiateAudioFormat();
|
||||
void selectAudioFormat(const QString& selectedCodecName);
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
class EntitiesScriptEngineProvider {
|
||||
public:
|
||||
virtual void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params = QStringList()) = 0;
|
||||
virtual void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
|
||||
const QStringList& params = QStringList(), const QUuid& remoteCallerID = QUuid()) = 0;
|
||||
virtual QFuture<QVariant> getLocalEntityScriptDetails(const EntityItemID& entityID) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -566,6 +566,11 @@ void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method,
|
|||
}
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::callEntityServerMethod(QUuid id, const QString& method, const QStringList& params) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
DependencyManager::get<EntityScriptClient>()->callEntityServerMethod(id, method, params);
|
||||
}
|
||||
|
||||
QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
|
|
|
@ -188,11 +188,11 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE void deleteEntity(QUuid entityID);
|
||||
|
||||
/// Allows a script to call a method on an entity's script. The method will execute in the entity script
|
||||
/// engine. If the entity does not have an entity script or the method does not exist, this call will have
|
||||
/// no effect.
|
||||
/**jsdoc
|
||||
* Call a method on an entity. If it is running an entity script (specified by the `script` property)
|
||||
* Call a method on an entity. Allows a script to call a method on an entity's script.
|
||||
* The method will execute in the entity script engine. If the entity does not have an
|
||||
* entity script or the method does not exist, this call will have no effect.
|
||||
* If it is running an entity script (specified by the `script` property)
|
||||
* and it exposes a property with the specified name `method`, it will be called
|
||||
* using `params` as the list of arguments.
|
||||
*
|
||||
|
@ -203,10 +203,29 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
||||
|
||||
/// finds the closest model to the center point, within the radius
|
||||
/// will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
/**jsdoc
|
||||
* Call a server method on an entity. Allows a client entity script to call a method on an
|
||||
* entity's server script. The method will execute in the entity server script engine. If
|
||||
* the entity does not have an entity server script or the method does not exist, this call will
|
||||
* have no effect. If the entity is running an entity script (specified by the `serverScripts` property)
|
||||
* and it exposes a property with the specified name `method`, it will be called using `params` as
|
||||
* the list of arguments.
|
||||
*
|
||||
* @function Entities.callEntityServerMethod
|
||||
* @param {EntityID} entityID The ID of the entity to call the method on.
|
||||
* @param {string} method The name of the method to call.
|
||||
* @param {string[]} params The list of parameters to call the specified method with.
|
||||
*/
|
||||
Q_INVOKABLE void callEntityServerMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList());
|
||||
|
||||
/**jsdoc
|
||||
* finds the closest model to the center point, within the radius
|
||||
* will return a EntityItemID.isKnownID = false if no models are in the radius
|
||||
* this function will not find any models in script engine contexts which don't have access to models
|
||||
* @function Entities.findClosestEntity
|
||||
* @param {vec3} center point
|
||||
* @param {float} radius to search
|
||||
* @return {EntityID} The EntityID of the entity that is closest and in the radius.
|
||||
*/
|
||||
Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const;
|
||||
|
||||
|
|
|
@ -69,6 +69,30 @@ bool EntityScriptClient::reloadServerScript(QUuid entityID) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void EntityScriptClient::callEntityServerMethod(QUuid entityID, const QString& method, const QStringList& params) {
|
||||
// Send packet to entity script server
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
|
||||
|
||||
if (entityScriptServer) {
|
||||
auto packetList = NLPacketList::create(PacketType::EntityScriptCallMethod, QByteArray(), true, true);
|
||||
|
||||
packetList->write(entityID.toRfc4122());
|
||||
|
||||
packetList->writeString(method);
|
||||
|
||||
quint16 paramCount = params.length();
|
||||
packetList->writePrimitive(paramCount);
|
||||
|
||||
foreach(const QString& param, params) {
|
||||
packetList->writeString(param);
|
||||
}
|
||||
|
||||
nodeList->sendPacketList(std::move(packetList), *entityScriptServer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
|
||||
|
|
|
@ -58,6 +58,8 @@ public:
|
|||
|
||||
bool reloadServerScript(QUuid entityID);
|
||||
MessageID getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback);
|
||||
void callEntityServerMethod(QUuid id, const QString& method, const QStringList& params);
|
||||
|
||||
|
||||
private slots:
|
||||
void handleNodeKilled(SharedNodePointer node);
|
||||
|
|
|
@ -123,6 +123,7 @@ public:
|
|||
ReplicatedBulkAvatarData,
|
||||
OctreeFileReplacementFromUrl,
|
||||
ChallengeOwnership,
|
||||
EntityScriptCallMethod,
|
||||
NUM_PACKET_TYPE
|
||||
};
|
||||
|
||||
|
|
|
@ -2476,7 +2476,7 @@ void ScriptEngine::callWithEnvironment(const EntityItemID& entityID, const QUrl&
|
|||
doWithEnvironment(entityID, sandboxURL, operation);
|
||||
}
|
||||
|
||||
void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params) {
|
||||
void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params, const QUuid& remoteCallerID) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||
|
@ -2486,7 +2486,8 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
|
|||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
||||
Q_ARG(const EntityItemID&, entityID),
|
||||
Q_ARG(const QString&, methodName),
|
||||
Q_ARG(const QStringList&, params));
|
||||
Q_ARG(const QStringList&, params),
|
||||
Q_ARG(const QUuid&, remoteCallerID));
|
||||
return;
|
||||
}
|
||||
#ifdef THREAD_DEBUGGING
|
||||
|
@ -2500,13 +2501,41 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
|
|||
if (isEntityScriptRunning(entityID)) {
|
||||
EntityScriptDetails details = _entityScripts[entityID];
|
||||
QScriptValue entityScript = details.scriptObject; // previously loaded
|
||||
if (entityScript.property(methodName).isFunction()) {
|
||||
|
||||
// If this is a remote call, we need to check to see if the function is remotely callable
|
||||
// we do this by checking for the existance of the 'remotelyCallable' property on the
|
||||
// entityScript. And we confirm that the method name is included. If this fails, the
|
||||
// function will not be called.
|
||||
bool callAllowed = false;
|
||||
if (remoteCallerID == QUuid()) {
|
||||
callAllowed = true;
|
||||
} else {
|
||||
if (entityScript.property("remotelyCallable").isArray()) {
|
||||
auto callables = entityScript.property("remotelyCallable");
|
||||
auto callableCount = callables.property("length").toInteger();
|
||||
for (int i = 0; i < callableCount; i++) {
|
||||
auto callable = callables.property(i).toString();
|
||||
if (callable == methodName) {
|
||||
callAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!callAllowed) {
|
||||
qDebug() << "Method [" << methodName << "] not remotely callable.";
|
||||
}
|
||||
}
|
||||
|
||||
if (callAllowed && entityScript.property(methodName).isFunction()) {
|
||||
QScriptValueList args;
|
||||
args << entityID.toScriptValue(this);
|
||||
args << qScriptValueFromSequence(this, params);
|
||||
callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args);
|
||||
}
|
||||
|
||||
QScriptValue oldData = this->globalObject().property("Script").property("remoteCallerID");
|
||||
this->globalObject().property("Script").setProperty("remoteCallerID", remoteCallerID.toString()); // Make the remoteCallerID available to javascript as a global.
|
||||
callWithEnvironment(entityID, details.definingSandboxURL, entityScript.property(methodName), entityScript, args);
|
||||
this->globalObject().property("Script").setProperty("remoteCallerID", oldData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -198,7 +198,8 @@ public:
|
|||
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
|
||||
Q_INVOKABLE void unloadAllEntityScripts();
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
|
||||
const QStringList& params = QStringList()) override;
|
||||
const QStringList& params = QStringList(),
|
||||
const QUuid& remoteCallerID = QUuid()) override;
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event);
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
|
||||
|
||||
|
|
Loading…
Reference in a new issue