aboutsummaryrefslogtreecommitdiff
path: root/advtrains_luaautomation
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_luaautomation')
-rwxr-xr-x[-rw-r--r--]advtrains_luaautomation/README.md11
-rw-r--r--advtrains_luaautomation/active_common.lua18
-rw-r--r--advtrains_luaautomation/atc_rail.lua9
-rwxr-xr-x[-rw-r--r--]advtrains_luaautomation/environment.lua14
-rw-r--r--advtrains_luaautomation/init.lua5
-rw-r--r--advtrains_luaautomation/mesecon_controller.lua259
-rw-r--r--advtrains_luaautomation/operation_panel.lua2
-rw-r--r--advtrains_luaautomation/pcnaming.lua7
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.pngbin0 -> 2196 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.pngbin0 -> 2188 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.pngbin0 -> 2191 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_LED_D.pngbin0 -> 2200 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_bottom.pngbin0 -> 222 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_sides.pngbin0 -> 504 bytes
-rw-r--r--advtrains_luaautomation/textures/atlatc_luacontroller_top.pngbin0 -> 8440 bytes
15 files changed, 306 insertions, 19 deletions
diff --git a/advtrains_luaautomation/README.md b/advtrains_luaautomation/README.md
index 683e45c..67a4b80 100644..100755
--- a/advtrains_luaautomation/README.md
+++ b/advtrains_luaautomation/README.md
@@ -260,6 +260,8 @@ There are several functions available especially for shunting operations. Some o
- `split_at_index(index, atc_command)`
Splits the train at the specified index, into a train with index-1 wagons and a second train starting with the index-th wagon. The `atc_command` specified is sent to the second train after decoupling. `"S0"` or `"B0"` is common to ensure any locomotives in the remaining train don't continue to move.
+ `index` must be more than 1 to avoid trying to decouple the very front of a train.
+
Example: train has wagons `"foo","foo","foo","bar","bar","bar"`
Command: `split_at_index(4,"S0")`
Result: first train (continues at previous speed): `"foo","foo","foo"`, second train (slows at S0): `"bar","bar","bar"`
@@ -312,13 +314,16 @@ Deprecated:
#### Interlocking
-This additional function is available when advtrains_interlocking is enabled:
+These additional functions are available when advtrains_interlocking is enabled:
- - `atc_set_disable_ars(boolean)`
+ - `atc_set_ars_disable(boolean)`
Disables (true) or enables (false) the use of ARS for this train. The train will not trigger ARS (automatic route setting) on signals then.
- Note: If you want to disable ARS from an approach callback, the call to `atc_set_disable_ars(true)` *must* happen during the approach callback, and may not be deferred to an interrupt(). Else the train might trigger an ARS before the interrupt fires.
+ Note: If you want to disable ARS from an approach callback, the call to `atc_set_ars_disable(true)` *must* happen during the approach callback, and may not be deferred to an interrupt(). Else the train might trigger an ARS before the interrupt fires.
+ - `section_occupancy(section_id)`
+ Returns a table of train ids for the specified section, nil if no section id is provided, false if the section id is invalid, an empty table if the section id is valid but empty of trains.
+
#### Approach callbacks
The LuaATC interface provides a way to hook into the approach callback system, which is for example used in the TSR rails (provided by advtrains_interlocking) or the station tracks (provided by advtrains_lines). However, for compatibility reasons, this behavior needs to be explicitly enabled.
diff --git a/advtrains_luaautomation/active_common.lua b/advtrains_luaautomation/active_common.lua
index 9bf8377..50fb2bc 100644
--- a/advtrains_luaautomation/active_common.lua
+++ b/advtrains_luaautomation/active_common.lua
@@ -14,7 +14,7 @@ end
function ac.after_place_node(pos, player)
local meta=minetest.get_meta(pos)
meta:set_string("formspec", ac.getform(pos, meta))
- meta:set_string("infotext", "LuaAutomation component, unconfigured.")
+ meta:set_string("infotext", "LuaATC component, unconfigured.")
local ph=minetest.pos_to_string(pos)
--just get first available key!
for en,_ in pairs(atlatc.envs) do
@@ -48,7 +48,7 @@ function ac.getform(pos, meta_p)
.."button[5,0.2;2,1;save;Save]"
.."button[7,0.2;3,1;cle;Clear Local Env.]"
.."textarea[0.3,1.5;"..atlatc.CODE_FORM_SIZE..";code;Code;"..minetest.formspec_escape(code).."]"
- .."label[0,9.7;"..err.."]"
+ .."label["..atlatc.CODE_FORM_ERRLABELPOS..";"..err.."]"
return form
end
@@ -91,17 +91,17 @@ function ac.on_receive_fields(pos, formname, fields, player)
meta:set_string("formspec", ac.getform(pos, meta))
if nodetbl.env then
- meta:set_string("infotext", "LuaAutomation component, assigned to environment '"..nodetbl.env.."'")
+ meta:set_string("infotext", "LuaATC component, assigned to environment '"..nodetbl.env.."'")
else
- meta:set_string("infotext", "LuaAutomation component, invalid enviroment set!")
+ meta:set_string("infotext", "LuaATC component, invalid enviroment set!")
end
end
-function ac.run_in_env(pos, evtdata, customfct_p)
+function ac.run_in_env(pos, evtdata, customfct_p, ignore_no_code)
local ph=minetest.pos_to_string(pos)
local nodetbl = ac.nodes[ph]
if not nodetbl then
- atwarn("LuaAutomation component at",ph,": Data not in memory! Please visit component and click 'Save'!")
+ atwarn("LuaATC component at",ph,": Data not in memory! Please visit component and click 'Save'!")
return
end
@@ -111,12 +111,14 @@ function ac.run_in_env(pos, evtdata, customfct_p)
end
if not nodetbl.env or not atlatc.envs[nodetbl.env] then
- atwarn("LuaAutomation component at",ph,": Not an existing environment: "..(nodetbl.env or "<nil>"))
+ atwarn("LuaATC component at",ph,": Not an existing environment: "..(nodetbl.env or "<nil>"))
return false
end
local env = atlatc.envs[nodetbl.env]
if not nodetbl.code or nodetbl.code=="" then
- env:log("warning", "LuaAutomation component at",ph,": No code to run! (insert -- to suppress warning)")
+ if not ignore_no_code then
+ env:log("warning", "LuaATC component at",ph,": No code to run! (insert -- to suppress warning)")
+ end
return false
end
diff --git a/advtrains_luaautomation/atc_rail.lua b/advtrains_luaautomation/atc_rail.lua
index b862129..5dde99c 100644
--- a/advtrains_luaautomation/atc_rail.lua
+++ b/advtrains_luaautomation/atc_rail.lua
@@ -14,7 +14,7 @@ function r.fire_event(pos, evtdata, appr_internal)
local railtbl = atlatc.active.nodes[ph]
if not railtbl then
- atwarn("LuaAutomation ATC interface rail at",ph,": Data not in memory! Please visit position and click 'Save'!")
+ atwarn("LuaATC interface rail at",ph,": Data not in memory! Please visit position and click 'Save'!")
return
end
@@ -56,7 +56,7 @@ function r.fire_event(pos, evtdata, appr_internal)
split_at_index = function(index, cmd)
if not train_id then return false end
assertt(cmd, "string")
- if type(index) ~= "number" then
+ if type(index) ~= "number" or index < 2 then
return false
end
local new_id = advtrains.split_train_at_index(train, index)
@@ -130,9 +130,8 @@ function r.fire_event(pos, evtdata, appr_internal)
get_rc = function()
return train.routingcode
end,
- atc_reset = function(cmd)
+ atc_reset = function()
if not train_id then return false end
- assertt(cmd, "string")
advtrains.atc.train_reset_command(train)
return true
end,
@@ -188,7 +187,7 @@ advtrains.register_tracks("default", {
models_prefix="advtrains_dtrack",
models_suffix=".b3d",
shared_texture="advtrains_dtrack_shared_atc.png",
- description=atltrans("LuaAutomation ATC Rail"),
+ description=atltrans("LuaATC Rail"),
formats={},
get_additional_definiton = function(def, preset, suffix, rotation)
return {
diff --git a/advtrains_luaautomation/environment.lua b/advtrains_luaautomation/environment.lua
index 63aa68d..6b1a283 100644..100755
--- a/advtrains_luaautomation/environment.lua
+++ b/advtrains_luaautomation/environment.lua
@@ -150,7 +150,7 @@ local static_env = {
--interrupts are handled per node, position unknown. (same goes for digilines)
--however external interrupts can be set here.
interrupt_pos = function(parpos, imesg)
- local pos=atlatc.pcnaming.resolve_pos(parpos)
+ local pos=atlatc.pcnaming.resolve_pos(parpos, "interrupt_pos")
atlatc.interrupt.add(0, pos, {type="ext_int", ext_int=true, message=imesg})
end,
-- sends an atc command to train regardless of where it is in the world
@@ -223,6 +223,18 @@ if advtrains.interlocking then
local pos = atlatc.pcnaming.resolve_pos(signal)
return advtrains.interlocking.signal_set_aspect(pos)
end
+
+ --section_occupancy()
+ static_env.section_occupancy = function(ts_id)
+ if not ts_id then return nil end
+ ts_id = tostring(ts_id)
+ local response = advtrains.interlocking.db.get_ts(ts_id)
+ if response == nil then
+ return false
+ else
+ return response.trains
+ end
+ end
end
-- Lines-specific:
diff --git a/advtrains_luaautomation/init.lua b/advtrains_luaautomation/init.lua
index ab625b1..c51aa71 100644
--- a/advtrains_luaautomation/init.lua
+++ b/advtrains_luaautomation/init.lua
@@ -14,6 +14,8 @@ minetest.register_privilege("atlatc", { description = "Player can place and modi
--Size of code input forms in X,Y notation. Must be at least 10x10
atlatc.CODE_FORM_SIZE = "15,12"
+--Position of Error Label in Code Form
+atlatc.CODE_FORM_ERRLABELPOS = "0,12"
--assertt helper. error if a variable is not of a type
function assertt(var, typ)
@@ -31,6 +33,9 @@ dofile(mp.."/interrupt.lua")
dofile(mp.."/active_common.lua")
dofile(mp.."/atc_rail.lua")
dofile(mp.."/operation_panel.lua")
+if mesecon then
+ dofile(mp.."/mesecon_controller.lua")
+end
dofile(mp.."/pcnaming.lua")
dofile(mp.."/chatcmds.lua")
diff --git a/advtrains_luaautomation/mesecon_controller.lua b/advtrains_luaautomation/mesecon_controller.lua
new file mode 100644
index 0000000..bffff84
--- /dev/null
+++ b/advtrains_luaautomation/mesecon_controller.lua
@@ -0,0 +1,259 @@
+-- mesecon_controller.lua
+-- Mesecon-interfaceable Operation Panel alternative
+-- Looks like a Mesecon Luacontroller
+
+-- Luacontroller Adapted Code
+-- From Mesecons mod https://mesecons.net/
+-- (c) Jeija and Contributors
+
+local BASENAME = "advtrains_luaautomation:mesecon_controller"
+
+local rules = {
+ a = {x = -1, y = 0, z = 0, name="A"},
+ b = {x = 0, y = 0, z = 1, name="B"},
+ c = {x = 1, y = 0, z = 0, name="C"},
+ d = {x = 0, y = 0, z = -1, name="D"},
+}
+
+local function generate_name(ports)
+ local d = ports.d and 1 or 0
+ local c = ports.c and 1 or 0
+ local b = ports.b and 1 or 0
+ local a = ports.a and 1 or 0
+ return BASENAME..d..c..b..a
+end
+
+
+local function set_port(pos, rule, state)
+ if state then
+ mesecon.receptor_on(pos, {rule})
+ else
+ mesecon.receptor_off(pos, {rule})
+ end
+end
+
+local function clean_port_states(ports)
+ ports.a = ports.a and true or false
+ ports.b = ports.b and true or false
+ ports.c = ports.c and true or false
+ ports.d = ports.d and true or false
+end
+
+-- Local table for storing which Mesecons off events should be ignored
+-- Indexed by hex encoded position
+local ignored_off_events = {}
+
+local function set_port_states(pos, ports)
+ local node = advtrains.ndb.get_node(pos)
+ local name = node.name
+ clean_port_states(ports)
+ local vports = minetest.registered_nodes[name].virtual_portstates
+ local new_name = generate_name(ports)
+
+ if name ~= new_name and vports then
+ -- Problem:
+ -- We need to place the new node first so that when turning
+ -- off some port, it won't stay on because the rules indicate
+ -- there is an onstate output port there.
+ -- When turning the output off then, it will however cause feedback
+ -- so that the luacontroller will receive an "off" event by turning
+ -- its output off.
+ -- Solution / Workaround:
+ -- Remember which output was turned off and ignore next "off" event.
+ local ph=minetest.pos_to_string(pos)
+ local railtbl = atlatc.active.nodes[ph]
+ if not railtbl then return end
+
+ local ign = railtbl.ignored_off_events or {}
+ if ports.a and not vports.a and not mesecon.is_powered(pos, rules.a) then ign.A = true end
+ if ports.b and not vports.b and not mesecon.is_powered(pos, rules.b) then ign.B = true end
+ if ports.c and not vports.c and not mesecon.is_powered(pos, rules.c) then ign.C = true end
+ if ports.d and not vports.d and not mesecon.is_powered(pos, rules.d) then ign.D = true end
+ railtbl.ignored_off_events = ign
+
+ advtrains.ndb.swap_node(pos, {name = new_name, param2 = node.param2})
+
+ -- Apply mesecon state only if node loaded
+ -- If node is not loaded, mesecon update will occur on next load via on_updated_from_nodedb
+ if advtrains.is_node_loaded(pos) then
+ if ports.a ~= vports.a then set_port(pos, rules.a, ports.a) end
+ if ports.b ~= vports.b then set_port(pos, rules.b, ports.b) end
+ if ports.c ~= vports.c then set_port(pos, rules.c, ports.c) end
+ if ports.d ~= vports.d then set_port(pos, rules.d, ports.d) end
+ end
+ end
+end
+
+local function on_updated_from_nodedb(pos, newnode, oldnode)
+ -- Switch appropriate Mesecon receptors depending on the node change
+ local vports = minetest.registered_nodes[oldnode.name].virtual_portstates
+ local ports = minetest.registered_nodes[newnode.name].virtual_portstates
+ if ports.a ~= vports.a then set_port(pos, rules.a, ports.a) end
+ if ports.b ~= vports.b then set_port(pos, rules.b, ports.b) end
+ if ports.c ~= vports.c then set_port(pos, rules.c, ports.c) end
+ if ports.d ~= vports.d then set_port(pos, rules.d, ports.d) end
+end
+
+local function ignore_offevent(pos, rule)
+ local ph=minetest.pos_to_string(pos)
+ local railtbl = atlatc.active.nodes[ph]
+ if not railtbl then return nil end
+ local ign = railtbl.ignored_off_events
+ if ign and ign[rule.name] then
+ ign[rule.name] = nil
+ return true
+ end
+ return false
+end
+
+local valid_ports = {a=true, b=true, c=true, d=true}
+
+local function fire_event(pos, evtdata)
+ local customfct={
+ set_mesecon_outputs = function(states)
+ assertt(states, "table")
+ set_port_states(pos, states)
+ end,
+ get_mesecon_input = function(port)
+ local portl = string.lower(port)
+ if not valid_ports[portl] then
+ error("get_mesecon_input: Invalid port (expected a,b,c,d)")
+ end
+ if mesecon.is_powered(pos, rules[portl]) then
+ return true
+ end
+ return false
+ end,
+ }
+ atlatc.active.run_in_env(pos, evtdata, customfct, true)
+
+end
+
+local output_rules = {}
+local input_rules = {}
+
+local node_box = {
+ type = "fixed",
+ fixed = {
+ {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab
+ {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board
+ {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC
+ }
+}
+
+local selection_box = {
+ type = "fixed",
+ fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
+}
+
+for a = 0, 1 do -- 0 = off 1 = on
+for b = 0, 1 do
+for c = 0, 1 do
+for d = 0, 1 do
+ local cid = tostring(d)..tostring(c)..tostring(b)..tostring(a)
+ local node_name = BASENAME..cid
+ local top = "atlatc_luacontroller_top.png"
+ if a == 1 then
+ top = top.."^atlatc_luacontroller_LED_A.png"
+ end
+ if b == 1 then
+ top = top.."^atlatc_luacontroller_LED_B.png"
+ end
+ if c == 1 then
+ top = top.."^atlatc_luacontroller_LED_C.png"
+ end
+ if d == 1 then
+ top = top.."^atlatc_luacontroller_LED_D.png"
+ end
+
+ local groups
+ if a + b + c + d ~= 0 then
+ groups = {dig_immediate=2, not_in_creative_inventory=1, save_in_at_nodedb=1}
+ else
+ groups = {dig_immediate=2, save_in_at_nodedb=1}
+ end
+
+ output_rules[cid] = {}
+ input_rules[cid] = {}
+ if a == 1 then table.insert(output_rules[cid], rules.a) end
+ if b == 1 then table.insert(output_rules[cid], rules.b) end
+ if c == 1 then table.insert(output_rules[cid], rules.c) end
+ if d == 1 then table.insert(output_rules[cid], rules.d) end
+
+ if a == 0 then table.insert( input_rules[cid], rules.a) end
+ if b == 0 then table.insert( input_rules[cid], rules.b) end
+ if c == 0 then table.insert( input_rules[cid], rules.c) end
+ if d == 0 then table.insert( input_rules[cid], rules.d) end
+
+ local mesecons = {
+ effector = {
+ rules = input_rules[cid],
+ action_change = function (pos, _, rule_name, new_state)
+ if new_state == "off" then
+ -- check for ignored off event on this node
+ if ignore_offevent(pos, rule_name) then
+ return
+ end
+ end
+ --Note: rule_name is not a *name* but actually the full rule table (position + name field)
+ --Event format consistent with Mesecons Luacontroller event
+ atlatc.interrupt.add(0, pos, {type=new_state, [new_state]=true, pin=rule_name})
+ end,
+ },
+ receptor = {
+ state = mesecon.state.on,
+ rules = output_rules[cid]
+ },
+ }
+
+ minetest.register_node(node_name, {
+ description = "LuaATC Mesecon Controller",
+ drawtype = "nodebox",
+ tiles = {
+ top,
+ "atlatc_luacontroller_bottom.png",
+ "atlatc_luacontroller_sides.png",
+ "atlatc_luacontroller_sides.png",
+ "atlatc_luacontroller_sides.png",
+ "atlatc_luacontroller_sides.png"
+ },
+ inventory_image = top,
+ paramtype = "light",
+ is_ground_content = false,
+ groups = groups,
+ drop = BASENAME.."0000",
+ sunlight_propagates = true,
+ selection_box = selection_box,
+ node_box = node_box,
+ mesecons = mesecons,
+ -- Virtual portstates are the ports that
+ -- the node shows as powered up (light up).
+ virtual_portstates = {
+ a = a == 1,
+ b = b == 1,
+ c = c == 1,
+ d = d == 1,
+ },
+ after_dig_node = function (pos, node, player)
+ mesecon.receptor_off(pos, output_rules)
+ atlatc.active.after_dig_node(pos, node, player)
+ end,
+ after_place_node = atlatc.active.after_place_node,
+ on_receive_fields = atlatc.active.on_receive_fields,
+ advtrains = {
+ on_updated_from_nodedb = on_updated_from_nodedb
+ },
+ luaautomation = {
+ fire_event=fire_event
+ },
+ digiline = {
+ receptor = {},
+ effector = {
+ action = atlatc.active.on_digiline_receive
+ },
+ },
+ })
+end
+end
+end
+end
diff --git a/advtrains_luaautomation/operation_panel.lua b/advtrains_luaautomation/operation_panel.lua
index f8b93b5..bfbbda4 100644
--- a/advtrains_luaautomation/operation_panel.lua
+++ b/advtrains_luaautomation/operation_panel.lua
@@ -7,7 +7,7 @@ end
minetest.register_node("advtrains_luaautomation:oppanel", {
drawtype = "normal",
tiles={"atlatc_oppanel.png"},
- description = "LuaAutomation operation panel",
+ description = "LuaATC operation panel",
groups = {
cracky = 1,
save_in_at_nodedb=1,
diff --git a/advtrains_luaautomation/pcnaming.lua b/advtrains_luaautomation/pcnaming.lua
index ebb769f..71f4d9a 100644
--- a/advtrains_luaautomation/pcnaming.lua
+++ b/advtrains_luaautomation/pcnaming.lua
@@ -44,7 +44,12 @@ minetest.register_craftitem("advtrains_luaautomation:pcnaming",{
return
end
local node = advtrains.ndb.get_node(pos)
- if node.name and (minetest.get_item_group(node.name, "advtrains_signal")>0 or advtrains.is_passive(pos)) then
+ local ndef = minetest.registered_nodes[node.name]
+ if node.name and (
+ minetest.get_item_group(node.name, "advtrains_signal")>0 --is IL signal
+ or advtrains.is_passive(pos) -- is passive component
+ or (ndef and ndef.luaautomation) -- is active component
+ ) then
--look if this one already has a name
local pn=""
for name, npos in pairs(atlatc.pcnaming.name_map) do
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png
new file mode 100644
index 0000000..c6182cc
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_A.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png
new file mode 100644
index 0000000..04c2da0
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_B.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png
new file mode 100644
index 0000000..01f6ae4
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_C.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_LED_D.png b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_D.png
new file mode 100644
index 0000000..6c8a26f
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_LED_D.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png b/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png
new file mode 100644
index 0000000..7ae955c
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_bottom.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png b/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png
new file mode 100644
index 0000000..40f4b60
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_sides.png
Binary files differ
diff --git a/advtrains_luaautomation/textures/atlatc_luacontroller_top.png b/advtrains_luaautomation/textures/atlatc_luacontroller_top.png
new file mode 100644
index 0000000..a5059af
--- /dev/null
+++ b/advtrains_luaautomation/textures/atlatc_luacontroller_top.png
Binary files differ