SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
LUATreeNode.h
Go to the documentation of this file.
1 
5 #pragma once
6 
7 #include "tree/TreeNode.h"
8 #include "LUAFunctions.h"
9 
10 namespace ai {
11 
15 class LUATreeNode : public TreeNode {
16 protected:
17  lua_State* _s;
18 
19  TreeNodeStatus runLUA(const AIPtr& entity, int64_t deltaMillis) {
20  // get userdata of the behaviour tree node
21  const std::string name = "__meta_node_" + _type;
22  lua_getfield(_s, LUA_REGISTRYINDEX, name.c_str());
23 #if AI_LUA_SANTITY > 0
24  if (lua_isnil(_s, -1)) {
25  ai_log_error("LUA node: could not find lua userdata for %s", name.c_str());
26  return TreeNodeStatus::EXCEPTION;
27  }
28 #endif
29  // get metatable
30  lua_getmetatable(_s, -1);
31 #if AI_LUA_SANTITY > 0
32  if (!lua_istable(_s, -1)) {
33  ai_log_error("LUA node: userdata for %s doesn't have a metatable assigned", name.c_str());
34  return TreeNodeStatus::EXCEPTION;
35  }
36 #endif
37  // get execute() method
38  lua_getfield(_s, -1, "execute");
39  if (!lua_isfunction(_s, -1)) {
40  ai_log_error("LUA node: metatable for %s doesn't have the execute() function assigned", name.c_str());
41  return TreeNodeStatus::EXCEPTION;
42  }
43 
44  // push self onto the stack
45  lua_getfield(_s, LUA_REGISTRYINDEX, name.c_str());
46 
47  // first parameter is ai
48  if (luaAI_pushai(_s, entity) == 0) {
49  return TreeNodeStatus::EXCEPTION;
50  }
51 
52  // second parameter is dt
53  lua_pushinteger(_s, deltaMillis);
54 
55 #if AI_LUA_SANTITY > 0
56  if (!lua_isfunction(_s, -4)) {
57  ai_log_error("LUA node: expected to find a function on stack -4");
58  return TreeNodeStatus::EXCEPTION;
59  }
60  if (!lua_isuserdata(_s, -3)) {
61  ai_log_error("LUA node: expected to find the userdata on -3");
62  return TreeNodeStatus::EXCEPTION;
63  }
64  if (!lua_isuserdata(_s, -2)) {
65  ai_log_error("LUA node: second parameter should be the ai");
66  return TreeNodeStatus::EXCEPTION;
67  }
68  if (!lua_isinteger(_s, -1)) {
69  ai_log_error("LUA node: first parameter should be the delta millis");
70  return TreeNodeStatus::EXCEPTION;
71  }
72 #endif
73  const int error = lua_pcall(_s, 3, 1, 0);
74  if (error) {
75  ai_log_error("LUA node script: %s", lua_isstring(_s, -1) ? lua_tostring(_s, -1) : "Unknown Error");
76  // reset stack
77  lua_pop(_s, lua_gettop(_s));
78  return TreeNodeStatus::EXCEPTION;
79  }
80  const lua_Integer execstate = luaL_checkinteger(_s, -1);
81  if (execstate < 0 || execstate >= (lua_Integer)TreeNodeStatus::MAX_TREENODESTATUS) {
82  ai_log_error("LUA node: illegal tree node status returned: " LUA_INTEGER_FMT, execstate);
83  }
84 
85  // reset stack
86  lua_pop(_s, lua_gettop(_s));
87  return (TreeNodeStatus)execstate;
88  }
89 
90 public:
92  private:
93  lua_State* _s;
94  std::string _type;
95  public:
96  LUATreeNodeFactory(lua_State* s, const std::string& typeStr) :
97  _s(s), _type(typeStr) {
98  }
99 
100  inline const std::string& type() const {
101  return _type;
102  }
103 
104  TreeNodePtr create(const TreeNodeFactoryContext* ctx) const override {
105  return std::make_shared<LUATreeNode>(ctx->name, ctx->parameters, ctx->condition, _s, _type);
106  }
107  };
108 
109  LUATreeNode(const std::string& name, const std::string& parameters, const ConditionPtr& condition, lua_State* s, const std::string& type) :
110  TreeNode(name, parameters, condition), _s(s) {
111  _type = type;
112  }
113 
114  ~LUATreeNode() {
115  }
116 
117  TreeNodeStatus execute(const AIPtr& entity, int64_t deltaMillis) override {
118  if (TreeNode::execute(entity, deltaMillis) == CANNOTEXECUTE) {
119  return CANNOTEXECUTE;
120  }
121 
122 #if AI_EXCEPTIONS
123  try {
124 #endif
125  return state(entity, runLUA(entity, deltaMillis));
126 #if AI_EXCEPTIONS
127  } catch (...) {
128  ai_log_error("Exception while running lua tree node");
129  }
130  return state(entity, EXCEPTION);
131 #endif
132  }
133 };
134 
135 }
#define ai_log_error(...)
Logging macro to provide your own loggers.
Definition: Types.h:23
This factory will create tree nodes. It uses the TreeNodeFactoryContext to collect all the needed dat...
Definition: AIFactories.h:68
Definition: LUATreeNode.h:15
Definition: LUATreeNode.h:91
Context for ITreeNodeFactory.
Definition: AIFactories.h:15
virtual TreeNodeStatus execute(const AIPtr &entity, int64_t deltaMillis)
Definition: TreeNodeImpl.h:184
The base class for all behaviour tree actions.
Definition: TreeNode.h:88
TreeNodeStatus execute(const AIPtr &entity, int64_t deltaMillis) override
Definition: LUATreeNode.h:117