You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.6 KiB
Lua

local behavior_node = require 'behavior3.behavior_node'
local behavior_ret = require 'behavior3.behavior_ret'
local json = require 'json'
local meta = {
__newindex = function(_, k)
error(string.format('readonly:%s', k), 2)
end
}
local function const(t)
setmetatable(t, meta)
for _, v in pairs(t) do
if type(v) == 'table' then
const(v)
end
end
return t
end
local trees = {}
local mt = {}
mt.__index = mt
function mt:init(name, path)
path = path or './workspace/trees/'
self.name = name
self.tick = 0
local file, err = io.open(string.format("%s%s%s", path, name, '.json'), 'r')
assert(file, err)
local str = file:read('*a')
local data = const(json.decode(str))
self.root = behavior_node.new(data.root, self)
end
function mt:run(env)
-- print(string.format('===== tree:%s, tick:%s, stack:%d =====', self.name, self.tick, #env.stack))
if #env.stack > 0 then
local last_node = env.stack[#env.stack]
while last_node do
local ret = last_node:run(env)
if ret == behavior_ret.RUNNING then
break
end
last_node = env.stack[#env.stack]
end
else
self.root:run(env)
end
self.tick = self.tick + 1
end
function mt:interrupt(env)
if #env.stack > 0 then
env.inner_vars = {}
env.stack = {}
end
end
local function new_tree(name)
local tree = setmetatable({}, mt)
tree:init(name)
trees[name] = tree
return tree
end
local function new_env(params)
local env = {
inner_vars = {}, -- [k.."_"..node.id] => vars
vars = {},
stack = {},
last_ret = nil
}
for k, v in pairs(params) do
env[k] = v
end
function env:get_var(k)
return env.vars[k]
end
function env:set_var(k, v)
self.vars[k] = v
end
function env:get_inner_var(node, k)
return self.inner_vars[k .. '_' .. node.id]
end
function env:set_inner_var(node, k, v)
self.inner_vars[k .. '_' .. node.id] = v
end
function env:push_stack(node)
self.stack[#self.stack + 1] = node
end
function env:pop_stack()
local node = self.stack[#self.stack]
self.stack[#self.stack] = nil
return node
end
return env
end
local M = {}
function M.new(name, env_params)
local env = new_env(env_params)
local tree = trees[name] or new_tree(name)
return {
tree = tree,
run = function()
tree:run(env)
end,
interrupt = function()
tree:interrupt(env)
end,
}
end
return M