SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
ServerImpl.h
Go to the documentation of this file.
1 
4 #pragma once
5 
6 #include "Server.h"
7 #include "SelectHandler.h"
8 #include "PauseHandler.h"
9 #include "ResetHandler.h"
10 #include "StepHandler.h"
11 #include "ChangeHandler.h"
12 #include "AddNodeHandler.h"
13 #include "DeleteNodeHandler.h"
14 #include "UpdateNodeHandler.h"
15 
16 namespace ai {
17 
18 namespace {
19 const int SV_BROADCAST_CHRDETAILS = 1 << 0;
20 const int SV_BROADCAST_STATE = 1 << 1;
21 }
22 
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);
39 }
40 
41 inline Server::~Server() {
42  delete _selectHandler;
43  delete _pauseHandler;
44  delete _resetHandler;
45  delete _stepHandler;
46  delete _changeHandler;
47  delete _addNodeHandler;
48  delete _deleteNodeHandler;
49  delete _updateNodeHandler;
50  _network.removeListener(this);
51 }
52 
53 inline void Server::enqueueEvent(const Event& event) {
54  ScopedWriteLock scopedLock(_lock);
55  _events.push_back(event);
56 }
57 
58 inline void Server::onConnect(Client* client) {
59  Event event;
60  event.type = EV_NEWCONNECTION;
61  event.data.newClient = client;
62  enqueueEvent(event);
63 }
64 
65 inline void Server::onDisconnect(Client* /*client*/) {
66  ai_log("remote debugger disconnect (%i)", _network.getConnectedClients());
67  Zone* zone = _zone;
68  if (zone == nullptr) {
69  return;
70  }
71 
72  // if there are still connected clients left, don't disable the debug mode for the zone
73  if (_network.getConnectedClients() > 0) {
74  return;
75  }
76 
77  zone->setDebug(false);
78  if (_zone.compare_exchange_strong(zone, nullptr)) {
79  // restore the zone state if no player is left for debugging
80  const bool pauseState = _pause;
81  if (pauseState) {
82  pause(0, false);
83  }
84 
85  // only if noone else already started a new debug session
86  resetSelection();
87  }
88 }
89 
90 inline bool Server::start() {
91  return _network.start();
92 }
93 
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);
99  }
100 }
101 
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);
118  }
119 }
120 
121 inline void Server::broadcastState(const Zone* zone) {
122  _broadcastMask |= SV_BROADCAST_STATE;
123  AIStateMessage msg;
124  auto func = [&] (const AIPtr& ai) {
125  const ICharacterPtr& chr = ai->getCharacter();
126  const AIStateWorld b(chr->getId(), chr->getPosition(), chr->getOrientation(), chr->getAttributes());
127  msg.addState(b);
128  };
129  zone->execute(func);
130  _network.broadcast(msg);
131 }
132 
133 inline void Server::broadcastStaticCharacterDetails(const Zone* zone) {
134  const CharacterId id = _selectedCharacterId;
135  if (id == AI_NOTHING_SELECTED) {
136  return;
137  }
138 
139  static const auto func = [&] (const AIPtr& ai) {
140  if (!ai) {
141  return false;
142  }
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);
148 
149  const AICharacterStaticMessage msgStatic(ai->getId(), nodeStaticData);
150  _network.broadcast(msgStatic);
151  return true;
152  };
153  if (!zone->execute(id, func)) {
154  resetSelection();
155  }
156 }
157 
158 inline void Server::broadcastCharacterDetails(const Zone* zone) {
159  _broadcastMask |= SV_BROADCAST_CHRDETAILS;
160  const CharacterId id = _selectedCharacterId;
161  if (id == AI_NOTHING_SELECTED) {
162  return;
163  }
164 
165  static const auto func = [&] (const AIPtr& ai) {
166  if (!ai) {
167  return false;
168  }
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);
175 
176  AIStateAggro aggro;
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()));
181  }
182 
183  const AICharacterDetailsMessage msg(ai->getId(), aggro, root);
184  _network.broadcast(msg);
185  return true;
186  };
187  if (!zone->execute(id, func)) {
188  resetSelection();
189  }
190 }
191 
192 inline void Server::handleEvents(Zone* zone, bool pauseState) {
193  std::vector<Event> events;
194  {
195  ScopedReadLock scopedLock(_lock);
196  events = std::move(_events);
197  _events.clear();
198  }
199  for (Event& event : events) {
200  switch (event.type) {
201  case EV_SELECTION: {
202  if (zone == nullptr || event.data.characterId == AI_NOTHING_SELECTED) {
203  resetSelection();
204  } else {
205  _selectedCharacterId = event.data.characterId;
206  broadcastStaticCharacterDetails(zone);
207  if (pauseState) {
208  broadcastState(zone);
209  broadcastCharacterDetails(zone);
210  }
211  }
212  break;
213  }
214  case EV_STEP: {
215  const int64_t queuedStepMillis = event.data.stepMillis;
216  auto func = [=] (const AIPtr& ai) {
217  if (!ai->isPause())
218  return;
219  ai->setPause(false);
220  ai->update(queuedStepMillis, true);
221  ai->getBehaviour()->execute(ai, queuedStepMillis);
222  ai->setPause(true);
223  };
224  zone->executeParallel(func);
225  broadcastState(zone);
226  broadcastCharacterDetails(zone);
227  break;
228  }
229  case EV_RESET: {
230  static auto func = [] (const AIPtr& ai) {
231  ai->getBehaviour()->resetState(ai);
232  };
233  event.data.zone->executeParallel(func);
234  break;
235  }
236  case EV_PAUSE: {
237  const bool newPauseState = event.data.pauseState;
238  _pause = newPauseState;
239  if (zone != nullptr) {
240  auto func = [=] (const AIPtr& ai) {
241  ai->setPause(newPauseState);
242  };
243  zone->executeParallel(func);
244  _network.broadcast(AIPauseMessage(newPauseState));
245  // send the last time the most recent state until we unpause
246  if (newPauseState) {
247  broadcastState(zone);
248  broadcastCharacterDetails(zone);
249  }
250  }
251  break;
252  }
253  case EV_UPDATESTATICCHRDETAILS: {
254  broadcastStaticCharacterDetails(event.data.zone);
255  break;
256  }
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());
261  break;
262  }
263  case EV_ZONEADD: {
264  if (!_zones.insert(event.data.zone).second) {
265  return;
266  }
267  _names.clear();
268  for (const Zone* z : _zones) {
269  _names.push_back(z->getName());
270  }
271  _network.broadcast(AINamesMessage(_names));
272  break;
273  }
274  case EV_ZONEREMOVE: {
275  _zone.compare_exchange_strong(event.data.zone, nullptr);
276  if (_zones.erase(event.data.zone) != 1) {
277  return;
278  }
279  _names.clear();
280  for (const Zone* z : _zones) {
281  _names.push_back(z->getName());
282  }
283  _network.broadcast(AINamesMessage(_names));
284  break;
285  }
286  case EV_SETDEBUG: {
287  if (_pause) {
288  pause(0, false);
289  }
290 
291  Zone* nullzone = nullptr;
292  _zone = nullzone;
293  resetSelection();
294 
295  for (Zone* z : _zones) {
296  const bool debug = z->getName() == event.strData;
297  if (!debug) {
298  continue;
299  }
300  if (_zone.compare_exchange_strong(nullzone, z)) {
301  z->setDebug(debug);
302  }
303  }
304 
305  break;
306  }
307  case EV_MAX:
308  break;
309  }
310  }
311 }
312 
313 inline void Server::resetSelection() {
314  _selectedCharacterId = AI_NOTHING_SELECTED;
315 }
316 
317 inline bool Server::updateNode(const CharacterId& characterId, int32_t nodeId, const std::string& name, const std::string& type, const std::string& condition) {
318  Zone* zone = _zone;
319  if (zone == nullptr) {
320  return false;
321  }
322  const AIPtr& ai = zone->getAI(characterId);
323  const TreeNodePtr& node = ai->getBehaviour()->getId() == nodeId ? ai->getBehaviour() : ai->getBehaviour()->getChild(nodeId);
324  if (!node) {
325  return false;
326  }
327  ConditionParser conditionParser(_aiRegistry, condition);
328  const ConditionPtr& conditionPtr = conditionParser.getCondition();
329  if (!conditionPtr) {
330  ai_log_error("Failed to parse the condition '%s'", condition.c_str());
331  return false;
332  }
333  TreeNodeParser treeNodeParser(_aiRegistry, type);
334  TreeNodePtr newNode = treeNodeParser.getTreeNode(name);
335  if (!newNode) {
336  ai_log_error("Failed to parse the node '%s'", type.c_str());
337  return false;
338  }
339  newNode->setCondition(conditionPtr);
340  for (auto& child : node->getChildren()) {
341  newNode->addChild(child);
342  }
343 
344  const TreeNodePtr& root = ai->getBehaviour();
345  if (node == root) {
346  ai->setBehaviour(newNode);
347  } else {
348  const TreeNodePtr& parent = root->getParent(root, nodeId);
349  if (!parent) {
350  ai_log_error("No parent for non-root node '%i'", nodeId);
351  return false;
352  }
353  parent->replaceChild(nodeId, newNode);
354  }
355 
356  Event event;
357  event.type = EV_UPDATESTATICCHRDETAILS;
358  event.data.zone = zone;
359  enqueueEvent(event);
360  return true;
361 }
362 
363 inline bool Server::addNode(const CharacterId& characterId, int32_t parentNodeId, const std::string& name, const std::string& type, const std::string& condition) {
364  Zone* zone = _zone;
365  if (zone == nullptr) {
366  return false;
367  }
368  const AIPtr& ai = zone->getAI(characterId);
369  TreeNodePtr node = ai->getBehaviour();
370  if (node->getId() != parentNodeId) {
371  node = node->getChild(parentNodeId);
372  }
373  if (!node) {
374  return false;
375  }
376  ConditionParser conditionParser(_aiRegistry, condition);
377  const ConditionPtr& conditionPtr = conditionParser.getCondition();
378  if (!conditionPtr) {
379  ai_log_error("Failed to parse the condition '%s'", condition.c_str());
380  return false;
381  }
382  TreeNodeParser treeNodeParser(_aiRegistry, type);
383  TreeNodePtr newNode = treeNodeParser.getTreeNode(name);
384  if (!newNode) {
385  ai_log_error("Failed to parse the node '%s'", type.c_str());;
386  return false;
387  }
388  newNode->setCondition(conditionPtr);
389  if (!node->addChild(newNode)) {
390  return false;
391  }
392 
393  Event event;
394  event.type = EV_UPDATESTATICCHRDETAILS;
395  event.data.zone = zone;
396  enqueueEvent(event);
397  return true;
398 }
399 
400 inline bool Server::deleteNode(const CharacterId& characterId, int32_t nodeId) {
401  Zone* zone = _zone;
402  if (zone == nullptr) {
403  return false;
404  }
405  const AIPtr& ai = zone->getAI(characterId);
406  // don't delete the root
407  const TreeNodePtr& root = ai->getBehaviour();
408  if (root->getId() == nodeId) {
409  return false;
410  }
411 
412  const TreeNodePtr& parent = root->getParent(root, nodeId);
413  if (!parent) {
414  ai_log_error("No parent for non-root node '%i'", nodeId);
415  return false;
416  }
417  parent->replaceChild(nodeId, TreeNodePtr());
418  Event event;
419  event.type = EV_UPDATESTATICCHRDETAILS;
420  event.data.zone = zone;
421  enqueueEvent(event);
422  return true;
423 }
424 
425 inline void Server::addZone(Zone* zone) {
426  Event event;
427  event.type = EV_ZONEADD;
428  event.data.zone = zone;
429  enqueueEvent(event);
430 }
431 
432 inline void Server::removeZone(Zone* zone) {
433  Event event;
434  event.type = EV_ZONEREMOVE;
435  event.data.zone = zone;
436  enqueueEvent(event);
437 }
438 
439 inline void Server::setDebug(const std::string& zoneName) {
440  Event event;
441  event.type = EV_SETDEBUG;
442  event.strData = zoneName;
443  enqueueEvent(event);
444 }
445 
446 inline void Server::reset() {
447  Zone* zone = _zone;
448  if (zone == nullptr) {
449  return;
450  }
451  Event event;
452  event.type = EV_RESET;
453  event.data.zone = zone;
454  enqueueEvent(event);
455 }
456 
457 inline void Server::select(const ClientId& /*clientId*/, const CharacterId& id) {
458  Event event;
459  event.type = EV_SELECTION;
460  event.data.characterId = id;
461  enqueueEvent(event);
462 }
463 
464 inline void Server::pause(const ClientId& /*clientId*/, bool state) {
465  Event event;
466  event.type = EV_PAUSE;
467  event.data.pauseState = state;
468  enqueueEvent(event);
469 }
470 
471 inline void Server::step(int64_t stepMillis) {
472  Event event;
473  event.type = EV_STEP;
474  event.data.stepMillis = stepMillis;
475  enqueueEvent(event);
476 }
477 
478 inline void Server::update(int64_t deltaTime) {
479  _time += deltaTime;
480  const int clients = _network.getConnectedClients();
481  Zone* zone = _zone;
482  bool pauseState = _pause;
483  _broadcastMask = 0u;
484 
485  handleEvents(zone, pauseState);
486 
487  if (clients > 0 && zone != nullptr) {
488  if (!pauseState) {
489  if ((_broadcastMask & SV_BROADCAST_STATE) == 0) {
490  broadcastState(zone);
491  }
492  if ((_broadcastMask & SV_BROADCAST_CHRDETAILS) == 0) {
493  broadcastCharacterDetails(zone);
494  }
495  }
496  } else if (pauseState) {
497  pause(1, false);
498  resetSelection();
499  }
500  _network.update(deltaTime);
501 }
502 
503 }
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
Definition: Server.h:90
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