Make signal influence point (~halt point) specifiable
Also extend signal api necessarilymaster
parent
8df7bcf6b6
commit
8f8f009425
|
@ -10,6 +10,23 @@ local function can_dig_func(pos)
|
|||
return true
|
||||
end
|
||||
|
||||
local function aspect(b)
|
||||
return {
|
||||
main = {
|
||||
free = b,
|
||||
speed = -1,
|
||||
},
|
||||
shunt = {
|
||||
free = false,
|
||||
},
|
||||
dst = {
|
||||
free = true,
|
||||
speed = -1,
|
||||
},
|
||||
info = {}
|
||||
}
|
||||
end
|
||||
|
||||
for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", als="green"}}) do
|
||||
|
||||
advtrains.trackplacer.register_tracktype("advtrains:retrosignal", "")
|
||||
|
@ -64,6 +81,9 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
|||
else
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_off"..rotation, param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
get_aspect = function(pos, node)
|
||||
return aspect(r=="on")
|
||||
end
|
||||
},
|
||||
can_dig = can_dig_func,
|
||||
|
@ -117,6 +137,9 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
|||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_off"..rotation, param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
get_aspect = function(pos, node)
|
||||
return aspect(r=="on")
|
||||
end,
|
||||
getstate = f.ls,
|
||||
setstate = function(pos, node, newstate)
|
||||
if newstate == f.als then
|
||||
|
@ -180,6 +203,9 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
|||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_off", param2 = node.param2}, true)
|
||||
end
|
||||
end,
|
||||
get_aspect = function(pos, node)
|
||||
return aspect(r=="on")
|
||||
end,
|
||||
getstate = f.ls,
|
||||
setstate = function(pos, node, newstate)
|
||||
if newstate == f.als then
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
-- interlocking/database.lua
|
||||
-- saving the location of TCB's, their neighbors and their state
|
||||
--[[
|
||||
|
||||
== THIS COMMENT IS PARTIALLY INCORRECT AND OUTDATED! ==
|
||||
|
||||
The interlocking system is based on track circuits.
|
||||
Track circuit breaks must be manually set by the user. Signals must be assigned to track circuit breaks and to a direction(connid).
|
||||
To simplify the whole system, there is no overlap.
|
||||
|
@ -96,8 +99,12 @@ local ildb = {}
|
|||
local track_circuit_breaks = {}
|
||||
local track_sections = {}
|
||||
|
||||
-- Assignment of signals to TCBs
|
||||
local signal_assignments = {}
|
||||
|
||||
-- track+direction -> signal position
|
||||
local influence_points = {}
|
||||
|
||||
function ildb.load(data)
|
||||
if not data then return end
|
||||
if data.tcbs then
|
||||
|
@ -112,6 +119,9 @@ function ildb.load(data)
|
|||
if data.rs_locks then
|
||||
advtrains.interlocking.route.rte_locks = data.rs_locks
|
||||
end
|
||||
if data.influence_points then
|
||||
influence_points = data.influence_points
|
||||
end
|
||||
end
|
||||
|
||||
function ildb.save()
|
||||
|
@ -120,6 +130,7 @@ function ildb.save()
|
|||
ts=track_sections,
|
||||
signalass = signal_assignments,
|
||||
rs_locks = advtrains.interlocking.route.rte_locks,
|
||||
influence_points = influence_points,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -455,6 +466,61 @@ function ildb.set_sigd_for_signal(pos, sigd)
|
|||
end
|
||||
|
||||
|
||||
-- checks if a signal is influencing here
|
||||
function ildb.get_ip_signal(pts, connid)
|
||||
if influence_points[pts] then
|
||||
return influence_points[pts][connid]
|
||||
end
|
||||
end
|
||||
|
||||
-- Tries to get aspect to obey here, if there
|
||||
-- is a signal ip at this location
|
||||
-- auto-clears invalid assignments
|
||||
function ildb.get_ip_signal_asp(pts, connid)
|
||||
local p = ildb.get_ip_signal(pts, connid)
|
||||
if p then
|
||||
local asp = advtrains.interlocking.signal_get_aspect(p)
|
||||
if not asp then
|
||||
atlog("Clearing orphaned signal influence point", pts, "/", connid)
|
||||
ildb.clear_ip_signal(pts, connid)
|
||||
return nil
|
||||
end
|
||||
return asp
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- set signal assignment.
|
||||
function ildb.set_ip_signal(pts, connid, spos)
|
||||
if not influence_points[pts] then
|
||||
influence_points[pts] = {}
|
||||
end
|
||||
influence_points[pts][connid] = spos
|
||||
end
|
||||
-- clear signal assignment.
|
||||
function ildb.clear_ip_signal(pts, connid)
|
||||
influence_points[pts][connid] = nil
|
||||
for _,_ in pairs(influence_points[pts]) do
|
||||
return
|
||||
end
|
||||
influence_points[pts] = nil
|
||||
end
|
||||
|
||||
function ildb.get_ip_by_signalpos(spos)
|
||||
for pts,tab in pairs(influence_points) do
|
||||
for connid,pos in pairs(tab) do
|
||||
if vector.equals(pos, spos) then
|
||||
return pts, connid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- clear signal assignment given the signal position
|
||||
function ildb.clear_ip_by_signalpos(spos)
|
||||
local pts, connid = ildb.get_ip_by_signalpos(spos)
|
||||
if pts then ildb.clear_ip_signal(pts, connid) end
|
||||
end
|
||||
|
||||
|
||||
advtrains.interlocking.db = ildb
|
||||
|
||||
|
|
|
@ -227,7 +227,6 @@ function advtrains.interlocking.init_route_prog(pname, sigd)
|
|||
}
|
||||
advtrains.interlocking.visualize_route(sigd, player_rte_prog[pname].route, "prog_"..pname, player_rte_prog[pname].tmp_lcks, pname)
|
||||
minetest.chat_send_player(pname, "Route programming mode active. Punch TCBs to add route segments, punch turnouts to lock them.")
|
||||
minetest.chat_send_player(pname, "Type /at_rp_set <name> when you are done, /at_rp_discard to cancel route programming")
|
||||
end
|
||||
|
||||
local function get_last_route_item(origin, route)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
-- Signal API implementation
|
||||
|
||||
|
||||
--[[ Signal aspect table:
|
||||
--[[
|
||||
Signal aspect table:
|
||||
asp = {
|
||||
main = {
|
||||
free = <boolean>,
|
||||
|
@ -9,6 +10,14 @@ asp = {
|
|||
},
|
||||
shunt = {
|
||||
free = <boolean>,
|
||||
-- Whether train may proceed as shunt move, on sight
|
||||
-- main aspect takes precedence over this
|
||||
proceed_as_main = <boolean>,
|
||||
-- If an approaching train is a shunt move and "main.free" is set,
|
||||
-- the train may proceed as a train move under the "main" aspect
|
||||
-- If this is not set, shunt moves are NOT allowed to switch to
|
||||
-- a train move, and must stop even if "main.free" is set.
|
||||
-- This is intended to be used for "Halt for shunt moves" signs.
|
||||
}
|
||||
dst = {
|
||||
free = <boolean>,
|
||||
|
@ -17,21 +26,69 @@ asp = {
|
|||
info = {
|
||||
call_on = <boolean>, -- Call-on route, expect train in track ahead
|
||||
dead_end = <boolean>, -- Route ends on a dead end (e.g. bumper)
|
||||
w_speed = <integer>,
|
||||
-- "Warning speed restriction". Supposed for short-term speed
|
||||
-- restrictions which always override any other restrictions
|
||||
-- imposed by "speed" fields, until lifted by a value of -1
|
||||
}
|
||||
}
|
||||
Signals API:
|
||||
-- For "speed" and "w_speed" fields, a value of -1 means that the
|
||||
-- restriction is lifted. If they are omitted, the value imposed at
|
||||
-- the last aspect received remains valid.
|
||||
-- The "dst" subtable can be completely omitted when no explicit dst
|
||||
-- aspect should be signalled to the train. In this case, the last
|
||||
-- signalled dst aspect remains valid.
|
||||
|
||||
== How signals actually work in here ==
|
||||
Each signal (in the advtrains universe) is some node that has at least the
|
||||
following things:
|
||||
- An "influence point" that is set somewhere on a rail
|
||||
- An aspect which trains that pass the "influence point" have to obey
|
||||
|
||||
There can be static and dynamic signals. Static signals are, roughly
|
||||
spoken, signs, while dynamic signals are "real" signals which can display
|
||||
different things.
|
||||
|
||||
The node definition of a signal node should contain those fields:
|
||||
groups = {
|
||||
advtrains_signal = 2,
|
||||
advtrains_signal = 2,
|
||||
save_in_at_nodedb = 1,
|
||||
}
|
||||
advtrains = {
|
||||
function set_aspect(pos, node, asp)
|
||||
...
|
||||
-- This function gets called whenever the signal should display
|
||||
-- a new or changed signal aspect. It is not required that
|
||||
-- the signal actually displays the exact same aspect, since
|
||||
-- some signals can not do this by design.
|
||||
-- Example: pure shunt signals can not display a "main" aspect
|
||||
-- and have no effect on train moves, so they will only ever
|
||||
-- honor the shunt.free field for their aspect.
|
||||
|
||||
-- The aspect passed in here can always be queried using the
|
||||
-- advtrains.interlocking.signal_get_supposed_aspect(pos) function.
|
||||
|
||||
-- For static signals, this function should be completely omitted
|
||||
-- If this function is ommitted, it won't be possible to use
|
||||
-- route setting on this signal.
|
||||
end
|
||||
function get_aspect(pos, node)
|
||||
-- This function gets called by the train safety system. It
|
||||
should return the aspect that this signal actually displays,
|
||||
not preferably the input of set_aspect.
|
||||
-- For regular, full-featured light signals, they will probably
|
||||
honor all entries in the original aspect, however, e.g.
|
||||
simple shunt signals always return main.free=true regardless of
|
||||
the set_aspect input because they can not signal "Halt" to
|
||||
train moves.
|
||||
-- advtrains.interlocking.DANGER contains a default "all-danger" aspect.
|
||||
end
|
||||
}
|
||||
on_rightclick = advtrains.interlocking.signal_rc_handler
|
||||
can_dig = advtrains.interlocking.signal_can_dig
|
||||
after_dig_node = advtrains.interlocking.signal_after_dig
|
||||
|
||||
(If you need to specify custom can_dig or after_dig_node callbacks,
|
||||
please call those functions anyway!)
|
||||
]]--
|
||||
|
||||
local DANGER = {
|
||||
|
@ -48,6 +105,7 @@ local DANGER = {
|
|||
},
|
||||
info = {}
|
||||
}
|
||||
advtrains.interlocking.DANGER = DANGER
|
||||
|
||||
function advtrains.interlocking.update_signal_aspect(tcbs)
|
||||
if tcbs.signal then
|
||||
|
@ -60,6 +118,11 @@ function advtrains.interlocking.signal_can_dig(pos)
|
|||
return not advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||
end
|
||||
|
||||
function advtrains.interlocking.signal_after_dig(pos)
|
||||
-- clear influence point
|
||||
advtrains.interlocking.db.clear_ip_by_signalpos(pos)
|
||||
end
|
||||
|
||||
function advtrains.interlocking.signal_set_aspect(pos, asp)
|
||||
local node=advtrains.ndb.get_node(pos)
|
||||
local ndef=minetest.registered_nodes[node.name]
|
||||
|
@ -75,7 +138,7 @@ function advtrains.interlocking.signal_rc_handler(pos, node, player, itemstack,
|
|||
advtrains.interlocking.show_signalling_form(sigd, pname)
|
||||
else
|
||||
-- permit to set aspect manually
|
||||
minetest.show_formspec(pname, "at_il_sigasp_"..minetest.pos_to_string(pos), "field[aspect;Set Aspect (F/D)Speed(F/D)Speed(F/D);D0D0D]")
|
||||
minetest.show_formspec(pname, "at_il_sigasp_"..minetest.pos_to_string(pos), "field[aspect;Set Aspect (F/D)Speed(F/D)Speed(F/D) ['A' to assign IP];D0D0D]")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -85,6 +148,10 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
local pos
|
||||
if pts then pos = minetest.string_to_pos(pts) end
|
||||
if pos and fields.aspect then
|
||||
if fields.aspect == "A" then
|
||||
advtrains.interlocking.show_ip_form(pos, pname)
|
||||
return
|
||||
end
|
||||
local mfs, msps, dfs, dsps, shs = string.match(fields.aspect, "^([FD])([0-9]+)([FD])([0-9]+)([FD])$")
|
||||
local asp = {
|
||||
main = {
|
||||
|
@ -108,7 +175,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
end)
|
||||
|
||||
-- Returns the aspect the signal at pos is supposed to show
|
||||
function advtrains.interlocking.signal_get_aspect(pos)
|
||||
function advtrains.interlocking.signal_get_supposed_aspect(pos)
|
||||
local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||
if sigd then
|
||||
local tcbs = advtrains.interlocking.db.get_tcbs(sigd)
|
||||
|
@ -118,3 +185,121 @@ function advtrains.interlocking.signal_get_aspect(pos)
|
|||
end
|
||||
return DANGER;
|
||||
end
|
||||
|
||||
-- Returns the actual aspect of the signal at position, as returned by the nodedef.
|
||||
-- returns nil
|
||||
function advtrains.interlocking.signal_get_aspect(pos)
|
||||
local node=advtrains.ndb.get_node(pos)
|
||||
local ndef=minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.advtrains and ndef.advtrains.get_aspect then
|
||||
return ndef.advtrains.get_aspect(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
local players_assign_ip = {}
|
||||
|
||||
-- shows small info form for signal IP state/assignment
|
||||
-- only_notset: show only if it is not set yet (used by signal tcb assignment)
|
||||
function advtrains.interlocking.show_ip_form(pos, pname, only_notset)
|
||||
local form = "size[7,5]label[0.5,0.5;Signal at "..minetest.pos_to_string(pos).."]"
|
||||
local pts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos)
|
||||
if pts then
|
||||
form = form.."label[0.5,1.5;Influence point is set at "..pts.."/"..connid.."]"
|
||||
form = form.."button_exit[0.5,2.5; 5,1;show;Show]"
|
||||
form = form.."button_exit[0.5,3.5; 5,1;clear;Clear]"
|
||||
else
|
||||
form = form.."label[0.5,1.5;Influence point is not set.]"
|
||||
form = form.."label[0.5,2.0;It is recommended to set an influence point.]"
|
||||
form = form.."label[0.5,2.5;This is the point where trains will obey the signal.]"
|
||||
|
||||
form = form.."button_exit[0.5,3.5; 5,1;set;Set]"
|
||||
end
|
||||
if not only_notset or not pts then
|
||||
minetest.show_formspec(pname, "at_il_ipassign_"..minetest.pos_to_string(pos), form)
|
||||
end
|
||||
end
|
||||
|
||||
local function ipmarker(ipos, connid)
|
||||
local node_ok, conns, rhe = advtrains.get_rail_info_at(ipos, advtrains.all_tracktypes)
|
||||
if not node_ok then return end
|
||||
local yaw = advtrains.dir_to_angle(conns[connid].c)
|
||||
|
||||
-- using tcbmarker here
|
||||
local obj = minetest.add_entity(vector.add(ipos, {x=0, y=0.2, z=0}), "advtrains_interlocking:tcbmarker")
|
||||
if not obj then return end
|
||||
obj:set_yaw(yaw)
|
||||
obj:set_properties({
|
||||
textures = { "at_il_signal_ip.png" },
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
if not minetest.check_player_privs(pname, {train_operator=true, interlocking=true}) then
|
||||
return
|
||||
end
|
||||
local pts = string.match(formname, "^at_il_ipassign_([^_]+)$")
|
||||
local pos
|
||||
if pts then
|
||||
pos = minetest.string_to_pos(pts)
|
||||
end
|
||||
if pos then
|
||||
if fields.set then
|
||||
advtrains.interlocking.signal_init_ip_assign(pos, pname)
|
||||
elseif fields.clear then
|
||||
advtrains.interlocking.db.clear_ip_by_signalpos(pos)
|
||||
elseif fields.show then
|
||||
local ipts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos)
|
||||
if not ipts then return end
|
||||
local ipos = minetest.string_to_pos(ipts)
|
||||
ipmarker(ipos, connid)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- inits the signal IP assignment process
|
||||
function advtrains.interlocking.signal_init_ip_assign(pos, pname)
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
minetest.chat_send_player(pname, "Insufficient privileges to use this!")
|
||||
return
|
||||
end
|
||||
--remove old IP
|
||||
advtrains.interlocking.db.clear_ip_by_signalpos(pos)
|
||||
minetest.chat_send_player(pname, "Configuring Signal: Please look in train's driving direction and punch rail to set influence point.")
|
||||
|
||||
players_assign_ip[pname] = pos
|
||||
end
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||
local pname = player:get_player_name()
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
return
|
||||
end
|
||||
-- IP assignment
|
||||
local signalpos = players_assign_ip[pname]
|
||||
if signalpos then
|
||||
if vector.distance(pos, signalpos)<=50 then
|
||||
local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)
|
||||
if node_ok and #conns == 2 then
|
||||
|
||||
local yaw = player:get_look_horizontal()
|
||||
local plconnid = advtrains.yawToClosestConn(yaw, conns)
|
||||
|
||||
-- add assignment if not already present.
|
||||
local pts = advtrains.roundfloorpts(pos)
|
||||
if not advtrains.interlocking.db.get_ip_signal_asp(pts, plconnid) then
|
||||
advtrains.interlocking.db.set_ip_signal(pts, plconnid, signalpos)
|
||||
ipmarker(pos, plconnid)
|
||||
minetest.chat_send_player(pname, "Configuring Signal: Successfully set influence point")
|
||||
else
|
||||
minetest.chat_send_player(pname, "Configuring Signal: Influence point of another signal is already present!")
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(pname, "Configuring Signal: This is not a normal two-connection rail! Aborted.")
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(pname, "Configuring Signal: Node is too far away. Aborted.")
|
||||
end
|
||||
players_assign_ip[pname] = nil
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -49,8 +49,11 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
|
|||
local tcbpos = minetest.string_to_pos(tcbpts)
|
||||
advtrains.interlocking.show_tcb_form(tcbpos, pname)
|
||||
else
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
minetest.chat_send_player(pname, "Insufficient privileges to use this!")
|
||||
return
|
||||
end
|
||||
--unconfigured
|
||||
--TODO security
|
||||
minetest.chat_send_player(pname, "Configuring TCB: Please punch the rail you want to assign this TCB to.")
|
||||
|
||||
players_assign_tcb[pname] = pos
|
||||
|
@ -143,6 +146,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
|||
tcbs.routes = {}
|
||||
ildb.set_sigd_for_signal(pos, sigd)
|
||||
minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.")
|
||||
advtrains.interlocking.show_ip_form(pos, pname, true)
|
||||
else
|
||||
minetest.chat_send_player(pname, "Configuring TCB: Internal error, TCBS doesn't exist. Aborted.")
|
||||
end
|
||||
|
@ -173,11 +177,11 @@ local function mktcbformspec(tcbs, btnpref, offset, pname)
|
|||
tcbs.ts_id = nil
|
||||
form = form.."label[0.5,"..offset..";Side "..btnpref..": ".."End of interlocking]"
|
||||
form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_makeil;Create Interlocked Track Section]"
|
||||
if tcbs.section_free then
|
||||
form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setlocked;Section is free]"
|
||||
else
|
||||
form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setfree;Section is blocked]"
|
||||
end
|
||||
--if tcbs.section_free then
|
||||
--form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setlocked;Section is free]"
|
||||
--else
|
||||
--form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setfree;Section is blocked]"
|
||||
--end
|
||||
end
|
||||
if tcbs.signal then
|
||||
form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_sigdia;Signalling]"
|
||||
|
@ -483,7 +487,7 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte)
|
|||
if not tcbs.signal_name then tcbs.signal_name = "Signal at "..minetest.pos_to_string(sigd.p) end
|
||||
if not tcbs.routes then tcbs.routes = {} end
|
||||
|
||||
local form = "size[7,9]label[0.5,0.5;Signal at "..minetest.pos_to_string(sigd.p).."]"
|
||||
local form = "size[7,10]label[0.5,0.5;Signal at "..minetest.pos_to_string(sigd.p).."]"
|
||||
form = form.."field[0.8,1.5;5.2,1;name;Signal name;"..tcbs.signal_name.."]"
|
||||
form = form.."button[5.5,1.2;1,1;setname;Set]"
|
||||
|
||||
|
@ -524,12 +528,13 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte)
|
|||
form = form.."button[0.5,7;2,1;dsproute;Show]"
|
||||
if hasprivs then
|
||||
form = form.."button[2.5,7;1,1;delroute;Delete]"
|
||||
form = form.."button[3.5,7;2,1;renroute;Rename]"
|
||||
form = form.."button[3.5,7;2,1;editroute;Edit]"
|
||||
end
|
||||
end
|
||||
if hasprivs then
|
||||
form = form.."button[0.5,8;2.5,1;newroute;New Route]"
|
||||
form = form.."button[ 3,8;2.5,1;unassign;Unassign Signal]"
|
||||
form = form.."button[ 3,9;2.5,1;influp;Influence Point]"
|
||||
end
|
||||
end
|
||||
sig_pselidx[pname] = sel_rte
|
||||
|
@ -617,6 +622,10 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
minetest.chat_send_player(pname, "Please cancel route first!")
|
||||
end
|
||||
end
|
||||
if fields.influp and hasprivs then
|
||||
advtrains.interlocking.show_ip_form(tcbs.signal, pname)
|
||||
return
|
||||
end
|
||||
|
||||
if fields.auto then
|
||||
tcbs.route_auto = true
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 285 B |
Loading…
Reference in New Issue