History

Add support for sending requests to entity script server

Ryan Huffman committed 9 years ago

Commit 8137c591 parent 340eeb96 files · +261 −3Browse files

Showing the changes to libraries/networking/src/EntityScriptClient.cpp (1 of 6 files). Show all

Unified · Split

libraries/networking/src/EntityScriptClient.cpp+153−0
@@ -0,0 +1,153 @@
1#include "EntityScriptClient.h"
2#include "NodeList.h"
3#include "NetworkLogging.h"
4
5#include <QThread>
6
7MessageID EntityScriptClient::_currentID = 0;
8
9GetScriptStatusRequest::GetScriptStatusRequest(QUuid entityID) : _entityID(entityID) {
10}
11
12GetScriptStatusRequest::~GetScriptStatusRequest() {
13
14}
15
16void GetScriptStatusRequest::start() {
17 auto client = DependencyManager::get<EntityScriptClient>();
18 qDebug() << "Sending script status request";
19 client->getEntityServerScriptStatus(_entityID, [this](bool responseReceived) {
20 qDebug() << "Received script status request";
21 emit finished(this);
22 });
23}
24
25EntityScriptClient::EntityScriptClient() {
26 setCustomDeleter([](Dependency* dependency){
27 static_cast<EntityScriptClient*>(dependency)->deleteLater();
28 });
29
30 auto nodeList = DependencyManager::get<NodeList>();
31 auto& packetReceiver = nodeList->getPacketReceiver();
32
33 packetReceiver.registerListener(PacketType::EntityScriptGetStatusReply, this, "handleGetScriptStatusReply");
34
35 connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptClient::handleNodeKilled);
36 connect(nodeList.data(), &LimitedNodeList::clientConnectionToNodeReset,
37 this, &EntityScriptClient::handleNodeClientConnectionReset);
38}
39
40GetScriptStatusRequest* EntityScriptClient::createScriptStatusRequest(QUuid entityID) {
41 auto request = new GetScriptStatusRequest(entityID);
42
43 request->moveToThread(thread());
44
45 return request;
46}
47
48bool EntityScriptClient::reloadServerScript(QUuid entityID) {
49 // Send packet to entity script server
50 auto nodeList = DependencyManager::get<NodeList>();
51 SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
52
53 if (entityScriptServer) {
54 auto id = entityID.toRfc4122();
55 auto payloadSize = id.size();
56 auto packet = NLPacket::create(PacketType::ReloadEntityServerScript, payloadSize, true);
57
58 packet->write(id);
59
60 if (nodeList->sendPacket(std::move(packet), *entityScriptServer) != -1) {
61 return true;
62 }
63 }
64
65 return false;
66}
67
68MessageID EntityScriptClient::getEntityServerScriptStatus(QUuid entityID, GetScriptStatusCallback callback) {
69 auto nodeList = DependencyManager::get<NodeList>();
70 SharedNodePointer entityScriptServer = nodeList->soloNodeOfType(NodeType::EntityScriptServer);
71
72 if (entityScriptServer) {
73 auto packetList = NLPacketList::create(PacketType::EntityScriptGetStatus, QByteArray(), true, true);
74
75 auto messageID = ++_currentID;
76 packetList->writePrimitive(messageID);
77
78 packetList->write(entityID.toRfc4122());
79
80 if (nodeList->sendPacketList(std::move(packetList), *entityScriptServer) != -1) {
81 _pendingEntityScriptStatusRequests[entityScriptServer][messageID] = callback;
82
83 return messageID;
84 }
85 }
86
87 callback(false);
88 return INVALID_MESSAGE_ID;
89}
90
91void EntityScriptClient::handleGetScriptStatusReply(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
92 Q_ASSERT(QThread::currentThread() == thread());
93
94 MessageID messageID;
95 message->readPrimitive(&messageID);
96
97 auto status = message->readString();
98
99 // Check if we have any pending requests for this node
100 auto messageMapIt = _pendingEntityScriptStatusRequests.find(senderNode);
101 if (messageMapIt != _pendingEntityScriptStatusRequests.end()) {
102
103 // Found the node, get the MessageID -> Callback map
104 auto& messageCallbackMap = messageMapIt->second;
105
106 // Check if we have this pending request
107 auto requestIt = messageCallbackMap.find(messageID);
108 if (requestIt != messageCallbackMap.end()) {
109 auto callback = requestIt->second;
110 callback(true);
111 messageCallbackMap.erase(requestIt);
112 }
113
114 // Although the messageCallbackMap may now be empty, we won't delete the node until we have disconnected from
115 // it to avoid constantly creating/deleting the map on subsequent requests.
116 }
117}
118
119void EntityScriptClient::handleNodeKilled(SharedNodePointer node) {
120 Q_ASSERT(QThread::currentThread() == thread());
121
122 if (node->getType() != NodeType::EntityScriptServer) {
123 return;
124 }
125
126 forceFailureOfPendingRequests(node);
127}
128
129void EntityScriptClient::handleNodeClientConnectionReset(SharedNodePointer node) {
130 // a client connection to a Node was reset
131 // if it was an EntityScriptServer we need to cause anything pending to fail so it is re-attempted
132
133 if (node->getType() != NodeType::EntityScriptServer) {
134 return;
135 }
136
137 //qCDebug(entity_script_client) << "EntityScriptClient detected client connection reset handshake with Asset Server - failing any pending requests";
138
139 forceFailureOfPendingRequests(node);
140}
141
142void EntityScriptClient::forceFailureOfPendingRequests(SharedNodePointer node) {
143
144 {
145 auto messageMapIt = _pendingEntityScriptStatusRequests.find(node);
146 if (messageMapIt != _pendingEntityScriptStatusRequests.end()) {
147 for (const auto& value : messageMapIt->second) {
148 value.second(false);
149 }
150 messageMapIt->second.clear();
151 }
152 }
153}