Advertisement
Berntan

Keywordhandler.lua

Nov 27th, 2023
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.64 KB | None | 0 0
  1. -- Advanced NPC System by Jiddo
  2.  
  3. if KeywordHandler == nil then
  4.  
  5. KeywordNode = {
  6. keywords = nil,
  7. callback = nil,
  8. parameters = nil,
  9. children = nil,
  10. parent = nil,
  11. condition = nil,
  12. action = nil
  13. }
  14.  
  15. -- Created a new keywordnode with the given keywords, callback function and parameters and without any childNodes.
  16. function KeywordNode:new(keys, func, param, condition, action)
  17. local obj = {}
  18. obj.keywords = keys
  19. obj.callback = func
  20. obj.parameters = param
  21. obj.children = {}
  22. obj.condition = condition
  23. obj.action = action
  24. setmetatable(obj, self)
  25. self.__index = self
  26. return obj
  27. end
  28.  
  29. -- Calls the underlying callback function if it is not nil.
  30. function KeywordNode:processMessage(cid, message)
  31. return (self.callback == nil or self.callback(cid, message, self.keywords, self.parameters, self))
  32. end
  33.  
  34. function KeywordNode:processAction(cid)
  35. if not self.action then
  36. return
  37. end
  38.  
  39. local player = Player(cid)
  40. if not player then
  41. return
  42. end
  43.  
  44. self.action(player, self.parameters.npcHandler)
  45. end
  46.  
  47. -- Returns true if message contains all patterns/strings found in keywords.
  48. function KeywordNode:checkMessage(cid, message)
  49. if self.keywords.callback ~= nil then
  50. local ret, data = self.keywords.callback(self.keywords, message)
  51. if not ret then
  52. return false
  53. end
  54.  
  55. if self.condition and not self.condition(Player(cid), data) then
  56. return false
  57. end
  58. return true
  59. end
  60.  
  61. local data = {}
  62. local last = 0
  63. for _, keyword in ipairs(self.keywords) do
  64. if type(keyword) == 'string' then
  65. local a, b = string.find(message, keyword)
  66. if a == nil or b == nil or a < last then
  67. return false
  68. end
  69. if keyword:sub(1, 1) == '%' then
  70. data[#data + 1] = tonumber(message:sub(a, b)) or nil
  71. end
  72. last = a
  73. end
  74. end
  75.  
  76. if self.condition and not self.condition(Player(cid), data) then
  77. return false
  78. end
  79. return true
  80. end
  81.  
  82. -- Returns the parent of this node or nil if no such node exists.
  83. function KeywordNode:getParent()
  84. return self.parent
  85. end
  86.  
  87. -- Returns an array of the callback function parameters assosiated with this node.
  88. function KeywordNode:getParameters()
  89. return self.parameters
  90. end
  91.  
  92. -- Returns an array of the triggering keywords assosiated with this node.
  93. function KeywordNode:getKeywords()
  94. return self.keywords
  95. end
  96.  
  97. -- Adds a childNode to this node. Creates the childNode based on the parameters (k = keywords, c = callback, p = parameters)
  98. function KeywordNode:addChildKeyword(keywords, callback, parameters, condition, action)
  99. local new = KeywordNode:new(keywords, callback, parameters, condition, action)
  100. return self:addChildKeywordNode(new)
  101. end
  102.  
  103. function KeywordNode:addAliasKeyword(keywords)
  104. if #self.children == 0 then
  105. print('KeywordNode:addAliasKeyword no previous node found')
  106. return false
  107. end
  108.  
  109. local prevNode = self.children[#self.children]
  110. local new = KeywordNode:new(keywords, prevNode.callback, prevNode.parameters, prevNode.condition, prevNode.action)
  111. for i = 1, #prevNode.children do
  112. new:addChildKeywordNode(prevNode.children[i])
  113. end
  114. return self:addChildKeywordNode(new)
  115. end
  116.  
  117. -- Adds a pre-created childNode to this node. Should be used for example if several nodes should have a common child.
  118. function KeywordNode:addChildKeywordNode(childNode)
  119. self.children[#self.children + 1] = childNode
  120. childNode.parent = self
  121. return childNode
  122. end
  123.  
  124. KeywordHandler = {
  125. root = nil,
  126. lastNode = nil
  127. }
  128.  
  129. -- Creates a new keywordhandler with an empty rootnode.
  130. function KeywordHandler:new()
  131. local obj = {}
  132. obj.root = KeywordNode:new(nil, nil, nil)
  133. obj.lastNode = {}
  134. setmetatable(obj, self)
  135. self.__index = self
  136. return obj
  137. end
  138.  
  139. -- Resets the lastNode field, and this resetting the current position in the node hierarchy to root.
  140. function KeywordHandler:reset(cid)
  141. if self.lastNode[cid] then
  142. self.lastNode[cid] = nil
  143. end
  144. end
  145.  
  146. -- Makes sure the correct childNode of lastNode gets a chance to process the message.
  147. function KeywordHandler:processMessage(cid, message)
  148. local node = self:getLastNode(cid)
  149. if node == nil then
  150. error('No root node found.')
  151. return false
  152. end
  153.  
  154. local ret = self:processNodeMessage(node, cid, message)
  155. if ret then
  156. return true
  157. end
  158.  
  159. if node:getParent() then
  160. node = node:getParent() -- Search through the parent.
  161. local ret = self:processNodeMessage(node, cid, message)
  162. if ret then
  163. return true
  164. end
  165. end
  166.  
  167. if node ~= self:getRoot() then
  168. node = self:getRoot() -- Search through the root.
  169. local ret = self:processNodeMessage(node, cid, message)
  170. if ret then
  171. return true
  172. end
  173. end
  174. return false
  175. end
  176.  
  177. -- Tries to process the given message using the node parameter's children and calls the node's callback function if found.
  178. -- Returns the childNode which processed the message or nil if no such node was found.
  179. function KeywordHandler:processNodeMessage(node, cid, message)
  180. local messageLower = message:lower()
  181. for _, childNode in pairs(node.children) do
  182. if childNode:checkMessage(cid, messageLower) then
  183. local oldLast = self.lastNode[cid]
  184. self.lastNode[cid] = childNode
  185. childNode.parent = node -- Make sure node is the parent of childNode (as one node can be parent to several nodes).
  186. if childNode:processMessage(cid, message) then
  187. childNode:processAction(cid)
  188. return true
  189. end
  190. self.lastNode[cid] = oldLast
  191. end
  192. end
  193. return false
  194. end
  195.  
  196. -- Returns the root keywordnode
  197. function KeywordHandler:getRoot()
  198. return self.root
  199. end
  200.  
  201. -- Returns the last processed keywordnode or root if no last node is found.
  202. function KeywordHandler:getLastNode(cid)
  203. return self.lastNode[cid] or self:getRoot()
  204. end
  205.  
  206. -- Adds a new keyword to the root keywordnode. Returns the new node.
  207. function KeywordHandler:addKeyword(keys, callback, parameters, condition, action)
  208. return self:getRoot():addChildKeyword(keys, callback, parameters, condition, action)
  209. end
  210.  
  211. -- Adds an alias keyword for the previous node.
  212. function KeywordHandler:addAliasKeyword(keys)
  213. return self:getRoot():addAliasKeyword(keys)
  214. end
  215.  
  216. -- Moves the current position in the keyword hierarchy count steps upwards. Count defalut value = 1.
  217. -- This function MIGHT not work properly yet. Use at your own risk.
  218. function KeywordHandler:moveUp(cid, steps)
  219. if steps == nil or type(steps) ~= "number" then
  220. steps = 1
  221. end
  222. for i = 1, steps do
  223. if self.lastNode[cid] == nil then
  224. return nil
  225. end
  226. self.lastNode[cid] = self.lastNode[cid]:getParent() or self:getRoot()
  227. end
  228. return self.lastNode[cid]
  229. end
  230. end
  231.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement