19 const int SV_BROADCAST_CHRDETAILS = 1 << 0;
20 const int SV_BROADCAST_STATE = 1 << 1;
23 inline Server::Server(AIRegistry& aiRegistry,
short port,
const std::string& hostname) :
24 _aiRegistry(aiRegistry), _network(port, hostname), _selectedCharacterId(AI_NOTHING_SELECTED), _time(0L),
25 _selectHandler(new SelectHandler(*this)), _pauseHandler(new PauseHandler(*this)), _resetHandler(new ResetHandler(*this)),
26 _stepHandler(new StepHandler(*this)), _changeHandler(new ChangeHandler(*this)), _addNodeHandler(new AddNodeHandler(*this)),
27 _deleteNodeHandler(new DeleteNodeHandler(*this)), _updateNodeHandler(new UpdateNodeHandler(*this)), _pause(false), _zone(nullptr) {
28 _network.addListener(
this);
29 ProtocolHandlerRegistry& r = ai::ProtocolHandlerRegistry::get();
30 r.registerHandler(ai::PROTO_SELECT, _selectHandler);
31 r.registerHandler(ai::PROTO_PAUSE, _pauseHandler);
32 r.registerHandler(ai::PROTO_RESET, _resetHandler);
33 r.registerHandler(ai::PROTO_STEP, _stepHandler);
34 r.registerHandler(ai::PROTO_PING, &_nopHandler);
35 r.registerHandler(ai::PROTO_CHANGE, _changeHandler);
36 r.registerHandler(ai::PROTO_ADDNODE, _addNodeHandler);
37 r.registerHandler(ai::PROTO_DELETENODE, _deleteNodeHandler);
38 r.registerHandler(ai::PROTO_UPDATENODE, _updateNodeHandler);
41 inline Server::~Server() {
42 delete _selectHandler;
46 delete _changeHandler;
47 delete _addNodeHandler;
48 delete _deleteNodeHandler;
49 delete _updateNodeHandler;
50 _network.removeListener(
this);
53 inline void Server::enqueueEvent(
const Event& event) {
54 ScopedWriteLock scopedLock(_lock);
55 _events.push_back(event);
58 inline void Server::onConnect(Client* client) {
60 event.type = EV_NEWCONNECTION;
61 event.data.newClient = client;
65 inline void Server::onDisconnect(Client* ) {
66 ai_log(
"remote debugger disconnect (%i)", _network.getConnectedClients());
68 if (zone ==
nullptr) {
73 if (_network.getConnectedClients() > 0) {
77 zone->setDebug(
false);
78 if (_zone.compare_exchange_strong(zone,
nullptr)) {
80 const bool pauseState = _pause;
91 return _network.start();
94 inline void Server::addChildren(
const TreeNodePtr& node, std::vector<AIStateNodeStatic>& out)
const {
95 for (
const TreeNodePtr& childNode : node->getChildren()) {
96 const int32_t nodeId = childNode->getId();
97 out.push_back(
AIStateNodeStatic(nodeId, childNode->getName(), childNode->getType(), childNode->getParameters(), childNode->getCondition()->getName(), childNode->getCondition()->getParameters()));
98 addChildren(childNode, out);
102 inline void Server::addChildren(
const TreeNodePtr& node, AIStateNode& parent,
const AIPtr& ai)
const {
103 const TreeNodes& children = node->getChildren();
104 std::vector<bool> currentlyRunning(children.size());
105 node->getRunningChildren(ai, currentlyRunning);
106 const int64_t aiTime = ai->_time;
107 const std::size_t length = children.size();
108 for (std::size_t i = 0; i < length; ++i) {
109 const TreeNodePtr& childNode = children[i];
110 const int32_t
id = childNode->getId();
111 const ConditionPtr& condition = childNode->getCondition();
112 const std::string conditionStr = condition ? condition->getNameWithConditions(ai) :
"";
113 const int64_t lastRun = childNode->getLastExecMillis(ai);
114 const int64_t delta = lastRun == -1 ? -1 : aiTime - lastRun;
115 AIStateNode child(
id, conditionStr, delta, childNode->getLastStatus(ai), currentlyRunning[i]);
116 addChildren(childNode, child, ai);
117 parent.addChildren(child);
121 inline void Server::broadcastState(
const Zone* zone) {
122 _broadcastMask |= SV_BROADCAST_STATE;
124 auto func = [&] (
const AIPtr& ai) {
125 const ICharacterPtr& chr = ai->getCharacter();
126 const AIStateWorld b(chr->getId(), chr->getPosition(), chr->getOrientation(), chr->getAttributes());
133 inline void Server::broadcastStaticCharacterDetails(
const Zone* zone) {
134 const CharacterId
id = _selectedCharacterId;
135 if (
id == AI_NOTHING_SELECTED) {
139 static const auto func = [&] (
const AIPtr& ai) {
143 std::vector<AIStateNodeStatic> nodeStaticData;
144 const TreeNodePtr& node = ai->getBehaviour();
145 const int32_t nodeId = node->getId();
146 nodeStaticData.push_back(AIStateNodeStatic(nodeId, node->getName(), node->getType(), node->getParameters(), node->getCondition()->getName(), node->getCondition()->getParameters()));
147 addChildren(node, nodeStaticData);
149 const AICharacterStaticMessage msgStatic(ai->getId(), nodeStaticData);
153 if (!zone->execute(
id, func)) {
158 inline void Server::broadcastCharacterDetails(
const Zone* zone) {
159 _broadcastMask |= SV_BROADCAST_CHRDETAILS;
160 const CharacterId
id = _selectedCharacterId;
161 if (
id == AI_NOTHING_SELECTED) {
165 static const auto func = [&] (
const AIPtr& ai) {
169 const TreeNodePtr& node = ai->getBehaviour();
170 const int32_t nodeId = node->getId();
171 const ConditionPtr& condition = node->getCondition();
172 const std::string conditionStr = condition ? condition->getNameWithConditions(ai) :
"";
173 AIStateNode root(nodeId, conditionStr, _time - node->getLastExecMillis(ai), node->getLastStatus(ai),
true);
174 addChildren(node, root, ai);
177 const ai::AggroMgr::Entries& entries = ai->getAggroMgr().getEntries();
178 aggro.reserve(entries.size());
179 for (
const Entry& e : entries) {
180 aggro.addAggro(AIStateAggroEntry(e.getCharacterId(), e.getAggro()));
183 const AICharacterDetailsMessage msg(ai->getId(), aggro, root);
187 if (!zone->execute(
id, func)) {
192 inline void Server::handleEvents(Zone* zone,
bool pauseState) {
193 std::vector<Event> events;
195 ScopedReadLock scopedLock(_lock);
196 events = std::move(_events);
199 for (Event& event : events) {
200 switch (event.type) {
202 if (zone ==
nullptr || event.data.characterId == AI_NOTHING_SELECTED) {
205 _selectedCharacterId =
event.data.characterId;
206 broadcastStaticCharacterDetails(zone);
208 broadcastState(zone);
209 broadcastCharacterDetails(zone);
215 const int64_t queuedStepMillis =
event.data.stepMillis;
216 auto func = [=] (
const AIPtr& ai) {
220 ai->update(queuedStepMillis,
true);
221 ai->getBehaviour()->execute(ai, queuedStepMillis);
224 zone->executeParallel(func);
225 broadcastState(zone);
226 broadcastCharacterDetails(zone);
230 static auto func = [] (
const AIPtr& ai) {
231 ai->getBehaviour()->resetState(ai);
233 event.data.zone->executeParallel(func);
237 const bool newPauseState =
event.data.pauseState;
238 _pause = newPauseState;
239 if (zone !=
nullptr) {
240 auto func = [=] (
const AIPtr& ai) {
241 ai->setPause(newPauseState);
243 zone->executeParallel(func);
244 _network.
broadcast(AIPauseMessage(newPauseState));
247 broadcastState(zone);
248 broadcastCharacterDetails(zone);
253 case EV_UPDATESTATICCHRDETAILS: {
254 broadcastStaticCharacterDetails(event.data.zone);
257 case EV_NEWCONNECTION: {
258 _network.sendToClient(event.data.newClient, AIPauseMessage(pauseState));
259 _network.sendToClient(event.data.newClient, AINamesMessage(_names));
260 ai_log(
"new remote debugger connection (%i)", _network.getConnectedClients());
264 if (!_zones.insert(event.data.zone).second) {
268 for (
const Zone* z : _zones) {
269 _names.push_back(z->getName());
271 _network.
broadcast(AINamesMessage(_names));
274 case EV_ZONEREMOVE: {
275 _zone.compare_exchange_strong(event.data.zone,
nullptr);
276 if (_zones.erase(event.data.zone) != 1) {
280 for (
const Zone* z : _zones) {
281 _names.push_back(z->getName());
283 _network.
broadcast(AINamesMessage(_names));
291 Zone* nullzone =
nullptr;
295 for (Zone* z : _zones) {
296 const bool debug = z->getName() ==
event.strData;
300 if (_zone.compare_exchange_strong(nullzone, z)) {
313 inline void Server::resetSelection() {
314 _selectedCharacterId = AI_NOTHING_SELECTED;
317 inline bool Server::updateNode(
const CharacterId& characterId, int32_t nodeId,
const std::string& name,
const std::string& type,
const std::string& condition) {
319 if (zone ==
nullptr) {
322 const AIPtr& ai = zone->getAI(characterId);
323 const TreeNodePtr& node = ai->getBehaviour()->getId() == nodeId ? ai->getBehaviour() : ai->getBehaviour()->getChild(nodeId);
328 const ConditionPtr& conditionPtr = conditionParser.getCondition();
330 ai_log_error(
"Failed to parse the condition '%s'", condition.c_str());
334 TreeNodePtr newNode = treeNodeParser.getTreeNode(name);
336 ai_log_error(
"Failed to parse the node '%s'", type.c_str());
339 newNode->setCondition(conditionPtr);
340 for (
auto& child : node->getChildren()) {
341 newNode->addChild(child);
344 const TreeNodePtr& root = ai->getBehaviour();
346 ai->setBehaviour(newNode);
348 const TreeNodePtr& parent = root->getParent(root, nodeId);
350 ai_log_error(
"No parent for non-root node '%i'", nodeId);
353 parent->replaceChild(nodeId, newNode);
357 event.type = EV_UPDATESTATICCHRDETAILS;
358 event.data.zone = zone;
363 inline bool Server::addNode(
const CharacterId& characterId, int32_t parentNodeId,
const std::string& name,
const std::string& type,
const std::string& condition) {
365 if (zone ==
nullptr) {
368 const AIPtr& ai = zone->getAI(characterId);
369 TreeNodePtr node = ai->getBehaviour();
370 if (node->getId() != parentNodeId) {
371 node = node->getChild(parentNodeId);
377 const ConditionPtr& conditionPtr = conditionParser.getCondition();
379 ai_log_error(
"Failed to parse the condition '%s'", condition.c_str());
383 TreeNodePtr newNode = treeNodeParser.getTreeNode(name);
385 ai_log_error(
"Failed to parse the node '%s'", type.c_str());;
388 newNode->setCondition(conditionPtr);
389 if (!node->addChild(newNode)) {
394 event.type = EV_UPDATESTATICCHRDETAILS;
395 event.data.zone = zone;
402 if (zone ==
nullptr) {
405 const AIPtr& ai = zone->getAI(characterId);
407 const TreeNodePtr& root = ai->getBehaviour();
408 if (root->getId() == nodeId) {
412 const TreeNodePtr& parent = root->getParent(root, nodeId);
414 ai_log_error(
"No parent for non-root node '%i'", nodeId);
417 parent->replaceChild(nodeId, TreeNodePtr());
419 event.type = EV_UPDATESTATICCHRDETAILS;
420 event.data.zone = zone;
427 event.type = EV_ZONEADD;
428 event.data.zone = zone;
434 event.type = EV_ZONEREMOVE;
435 event.data.zone = zone;
441 event.type = EV_SETDEBUG;
442 event.strData = zoneName;
448 if (zone ==
nullptr) {
452 event.type = EV_RESET;
453 event.data.zone = zone;
459 event.type = EV_SELECTION;
460 event.data.characterId = id;
466 event.type = EV_PAUSE;
467 event.data.pauseState = state;
473 event.type = EV_STEP;
474 event.data.stepMillis = stepMillis;
480 const int clients = _network.getConnectedClients();
482 bool pauseState = _pause;
485 handleEvents(zone, pauseState);
487 if (clients > 0 && zone !=
nullptr) {
489 if ((_broadcastMask & SV_BROADCAST_STATE) == 0) {
490 broadcastState(zone);
492 if ((_broadcastMask & SV_BROADCAST_CHRDETAILS) == 0) {
493 broadcastCharacterDetails(zone);
496 }
else if (pauseState) {
500 _network.update(deltaTime);
bool deleteNode(const CharacterId &characterId, int32_t nodeId)
Delete the specified node from the ICharacter's behaviour tree and all the other characters that are ...
Definition: ServerImpl.h:400
#define ai_log_error(...)
Logging macro to provide your own loggers.
Definition: Types.h:23
Transforms the string representation of a TreeNode with all its parameters into a TreeNode instance...
Definition: TreeNodeParser.h:22
bool start()
Start to listen on the specified port.
Definition: ServerImpl.h:90
void removeZone(Zone *zone)
Removes a Zone from the server. After this call the given zone is no longer available for debugging p...
Definition: ServerImpl.h:432
bool broadcast(const IProtocolMessage &msg)
Definition: NetworkImpl.h:230
bool addNode(const CharacterId &characterId, int32_t parentNodeId, const std::string &name, const std::string &type, const std::string &condition)
Add a new node with the given values to the specified ICharacter and all the other characters that ar...
Definition: ServerImpl.h:363
void select(const ClientId &clientId, const CharacterId &id)
Select a particular character (resp. AI instance) and send detail information to all the connected cl...
Definition: ServerImpl.h:457
bool updateNode(const CharacterId &characterId, int32_t nodeId, const std::string &name, const std::string &type, const std::string &condition)
Update the specified node with the given values for the specified ICharacter and all the other charac...
Definition: ServerImpl.h:317
Definition: AIStubTypes.h:48
void reset()
Resets the AI states.
Definition: ServerImpl.h:446
void pause(const ClientId &clientId, bool pause)
Will pause/unpause the execution of the behaviour trees for all watched AI instances.
Definition: ServerImpl.h:464
Transforms the string representation of a condition with all its sub conditions and parameters into a...
Definition: ConditionParser.h:23
void setDebug(const std::string &zoneName)
Activate the debugging for this particular zone. And disables the debugging for every other zone...
Definition: ServerImpl.h:439
void addZone(Zone *zone)
Adds a new zone to this server instance that can be debugged. The server does not own this pointer so...
Definition: ServerImpl.h:425
#define ai_log(...)
Logging macro to provide your own loggers.
Definition: Types.h:16
void update(int64_t deltaTime)
call this to update the server - should get called somewhere from your game tick
Definition: ServerImpl.h:478
void step(int64_t stepMillis=1L)
Performs one step of the AI in pause mode.
Definition: ServerImpl.h:471