LuaAutomation: Add interrupt to the ingame API and implement initialization code handling and env management
parent
b19033b224
commit
948482a99e
|
@ -84,7 +84,7 @@ function ac.on_receive_fields(pos, formname, fields, player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ac.run_in_env(pos, evtdata, customfct)
|
function ac.run_in_env(pos, evtdata, customfct_p)
|
||||||
local ph=minetest.hash_node_position(pos)
|
local ph=minetest.hash_node_position(pos)
|
||||||
local nodetbl = ac.nodes[ph] or {}
|
local nodetbl = ac.nodes[ph] or {}
|
||||||
|
|
||||||
|
@ -100,6 +100,11 @@ function ac.run_in_env(pos, evtdata, customfct)
|
||||||
return false, "No code to run!"
|
return false, "No code to run!"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local customfct=customfct_p or {}
|
||||||
|
customfct.interrupt=function(t, imesg)
|
||||||
|
atlatc.interrupt.add(t, pos, {type="int", int=true, message=imesg})
|
||||||
|
end
|
||||||
|
|
||||||
local datain=nodetbl.data or {}
|
local datain=nodetbl.data or {}
|
||||||
local succ, dataout = atlatc.envs[nodetbl.env]:execute_code(datain, nodetbl.code, evtdata, customfct)
|
local succ, dataout = atlatc.envs[nodetbl.env]:execute_code(datain, nodetbl.code, evtdata, customfct)
|
||||||
if succ then
|
if succ then
|
||||||
|
|
|
@ -78,7 +78,7 @@ advtrains.register_tracks("default", {
|
||||||
advtrains = {
|
advtrains = {
|
||||||
on_train_enter = function(pos, train_id)
|
on_train_enter = function(pos, train_id)
|
||||||
--do async. Event is fired in train steps
|
--do async. Event is fired in train steps
|
||||||
atlatc.interrupt.add(0, pos, {type="train", id=train_id})
|
atlatc.interrupt.add(0, pos, {type="train", train=true, id=train_id})
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
luaautomation = {
|
luaautomation = {
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
--chatcmds.lua
|
||||||
|
--Registers commands to modify the init and step code for LuaAutomation
|
||||||
|
|
||||||
|
local function get_init_form(env)
|
||||||
|
local err = env.init_err or ""
|
||||||
|
local code = env.init_code or ""
|
||||||
|
atprint(err)
|
||||||
|
local form = "size[10,10]button[0,0;2,1;run;Run InitCode]button[2,0;2,1;cls;Clear S]"
|
||||||
|
.."button[4,0;2,1;save;Save] button[6,0;2,1;del;Delete Env.] textarea[0.2,1;10,10;code;Environment initialization code;"..minetest.formspec_escape(code).."]"
|
||||||
|
.."label[0,9.8;"..err.."]"
|
||||||
|
return form
|
||||||
|
end
|
||||||
|
|
||||||
|
core.register_chatcommand("env_setup", {
|
||||||
|
params = "<environment name>",
|
||||||
|
description = "Set up and modify AdvTrains LuaAutomation environment",
|
||||||
|
privs = {atlatc=true},
|
||||||
|
func = function(name, param)
|
||||||
|
local env=atlatc.envs[param]
|
||||||
|
if not env then return false,"Invalid environment name!" end
|
||||||
|
minetest.show_formspec(name, "atlatc_envsetup_"..param, get_init_form(env))
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
core.register_chatcommand("env_create", {
|
||||||
|
params = "<environment name>",
|
||||||
|
description = "Create an AdvTrains LuaAutomation environment",
|
||||||
|
privs = {atlatc=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if not param or param=="" then return false, "Name required!" end
|
||||||
|
if atlatc.envs[param] then return false, "Environment already exists!" end
|
||||||
|
atlatc.envs[param] = atlatc.env_new(param)
|
||||||
|
return true, "Created environment '"..param.."'. Use '/env_setup "..param.."' to define global initialization code, or start building LuaATC components!"
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
|
|
||||||
|
local pname=player:get_player_name()
|
||||||
|
if not minetest.check_player_privs(pname, {atlatc=true}) then return end
|
||||||
|
|
||||||
|
local envname=string.match(formname, "^atlatc_delconfirm_(.+)$")
|
||||||
|
if envname and fields.sure=="YES" then
|
||||||
|
atlatc.envs[envname]=nil
|
||||||
|
minetest.chat_send_player(pname, "Environment deleted!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
envname=string.match(formname, "^atlatc_envsetup_(.+)$")
|
||||||
|
if not envname then return end
|
||||||
|
|
||||||
|
local env=atlatc.envs[envname]
|
||||||
|
if not env then return end
|
||||||
|
|
||||||
|
if fields.del then
|
||||||
|
minetest.show_formspec(pname, "atlatc_delconfirm_"..envname, "field[sure;"..minetest.formspec_escape("SURE TO DELETE ENVIRONMENT "..envname.."? Type YES (all uppercase) to continue or just quit form to cancel.")..";]")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
env.init_err=nil
|
||||||
|
if fields.code then
|
||||||
|
env.init_code=fields.code
|
||||||
|
end
|
||||||
|
if fields.run then
|
||||||
|
env:run_initcode()
|
||||||
|
minetest.show_formspec(pname, formname, get_init_form(env))
|
||||||
|
end
|
||||||
|
end)
|
|
@ -25,6 +25,28 @@ function atlatc.remove_invalid_data(o, nested)
|
||||||
nested[o] = nil
|
nested[o] = nil
|
||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
function atlatc.replace_function_envs(o, fenv, nested)
|
||||||
|
if o==nil then return nil end
|
||||||
|
local valid_dt={["nil"]=true, boolean=true, number=true, string=true}
|
||||||
|
if type(o) ~= "table" then
|
||||||
|
--check valid data type
|
||||||
|
if type(o)=="function" then
|
||||||
|
setfenv(o, fenv)
|
||||||
|
end
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
-- Contains table -> true/nil of currently nested tables
|
||||||
|
nested = nested or {}
|
||||||
|
if nested[o] then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
nested[o] = true
|
||||||
|
for k, v in pairs(o) do
|
||||||
|
v = atlatc.replace_function_envs(v, fenv, nested)
|
||||||
|
end
|
||||||
|
nested[o] = nil
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local env_proto={
|
local env_proto={
|
||||||
|
@ -149,7 +171,15 @@ local static_env = {
|
||||||
POS = function(x,y,z) return {x=x, y=y, z=z} end,
|
POS = function(x,y,z) return {x=x, y=y, z=z} end,
|
||||||
getstate = p_api_getstate,
|
getstate = p_api_getstate,
|
||||||
setstate = p_api_setstate,
|
setstate = p_api_setstate,
|
||||||
|
--interrupts are handled per node, position unknown.
|
||||||
|
--however external interrupts can be set here.
|
||||||
|
interrupt_pos = function(pos, imesg)
|
||||||
|
if not type(pos)=="table" or not pos.x or not pos.y or not pos.z then
|
||||||
|
debug.sethook()
|
||||||
|
error("Invalid position supplied to interrupt_pos")
|
||||||
|
end
|
||||||
|
atlatc.interrupt.add(0, pos, {type="ext_int", ext_int=true, message=imesg})
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name in pairs(safe_globals) do
|
for _, name in pairs(safe_globals) do
|
||||||
|
@ -168,7 +198,6 @@ end
|
||||||
function env_proto:execute_code(fenv, code, evtdata, customfct)
|
function env_proto:execute_code(fenv, code, evtdata, customfct)
|
||||||
local metatbl ={
|
local metatbl ={
|
||||||
__index = function(t, i)
|
__index = function(t, i)
|
||||||
print("index metamethod:",i)
|
|
||||||
if i=="S" then
|
if i=="S" then
|
||||||
return self.sdata
|
return self.sdata
|
||||||
elseif i=="F" then
|
elseif i=="F" then
|
||||||
|
@ -193,6 +222,9 @@ function env_proto:execute_code(fenv, code, evtdata, customfct)
|
||||||
if not fun then
|
if not fun then
|
||||||
return false, err
|
return false, err
|
||||||
end
|
end
|
||||||
|
--set function environment for all functions residing in F, so they get the right variables. Else it's a huge mess...
|
||||||
|
atlatc.replace_function_envs(self.fdata, fenv)
|
||||||
|
|
||||||
setfenv(fun, fenv)
|
setfenv(fun, fenv)
|
||||||
local succ, data = pcall(fun)
|
local succ, data = pcall(fun)
|
||||||
if succ then
|
if succ then
|
||||||
|
@ -203,9 +235,11 @@ end
|
||||||
|
|
||||||
function env_proto:run_initcode()
|
function env_proto:run_initcode()
|
||||||
if self.init_code and self.init_code~="" then
|
if self.init_code and self.init_code~="" then
|
||||||
local succ, err = self:execute_code(self.init_code, nil, {}, "Global init code")
|
self.fdata = {}
|
||||||
|
atprint("[atlatc]Running initialization code for environment '"..self.name.."'")
|
||||||
|
local succ, err = self:execute_code({}, self.init_code, {type="init", init=true})
|
||||||
if not succ then
|
if not succ then
|
||||||
--TODO
|
self.init_err=err
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,6 +26,8 @@ dofile(mp.."/active_common.lua")
|
||||||
dofile(mp.."/atc_rail.lua")
|
dofile(mp.."/atc_rail.lua")
|
||||||
dofile(mp.."/operation_panel.lua")
|
dofile(mp.."/operation_panel.lua")
|
||||||
dofile(mp.."/p_mesecon_iface.lua")
|
dofile(mp.."/p_mesecon_iface.lua")
|
||||||
|
dofile(mp.."/chatcmds.lua")
|
||||||
|
|
||||||
|
|
||||||
local filename=minetest.get_worldpath().."/advtrains_luaautomation"
|
local filename=minetest.get_worldpath().."/advtrains_luaautomation"
|
||||||
local file, err = io.open(filename, "r")
|
local file, err = io.open(filename, "r")
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
-- API to passive components, as described in passive_api.txt
|
-- API to passive components, as described in passive_api.txt
|
||||||
|
|
||||||
local function getstate(pos)
|
local function getstate(pos)
|
||||||
|
if not type(pos)=="table" or not pos.x or not pos.y or not pos.z then
|
||||||
|
debug.sethook()
|
||||||
|
error("Invalid position supplied to getstate")
|
||||||
|
end
|
||||||
local node=advtrains.ndb.get_node(pos)
|
local node=advtrains.ndb.get_node(pos)
|
||||||
local ndef=minetest.registered_nodes[node.name]
|
local ndef=minetest.registered_nodes[node.name]
|
||||||
if ndef and ndef.luaautomation and ndef.luaautomation.getstate then
|
if ndef and ndef.luaautomation and ndef.luaautomation.getstate then
|
||||||
|
@ -16,6 +20,10 @@ local function getstate(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function setstate(pos, newstate)
|
local function setstate(pos, newstate)
|
||||||
|
if not type(pos)=="table" or not pos.x or not pos.y or not pos.z then
|
||||||
|
debug.sethook()
|
||||||
|
error("Invalid position supplied to setstate")
|
||||||
|
end
|
||||||
local node=advtrains.ndb.get_node(pos)
|
local node=advtrains.ndb.get_node(pos)
|
||||||
local ndef=minetest.registered_nodes[node.name]
|
local ndef=minetest.registered_nodes[node.name]
|
||||||
if ndef and ndef.luaautomation and ndef.luaautomation.setstate then
|
if ndef and ndef.luaautomation and ndef.luaautomation.setstate then
|
||||||
|
|
Loading…
Reference in New Issue