aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/tcb_ts_ui.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_interlocking/tcb_ts_ui.lua')
-rwxr-xr-xadvtrains_interlocking/tcb_ts_ui.lua830
1 files changed, 553 insertions, 277 deletions
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index 96edadb..0111f5e 100755
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -1,9 +1,15 @@
-- Track Circuit Breaks and Track Sections - Player interaction
+-- Get current translator
+local S = advtrains.interlocking.translate
+
local players_assign_tcb = {}
local players_assign_signal = {}
+local players_assign_xlink = {}
local players_link_ts = {}
+local players_assign_fixedlocks = {}
+local atil = advtrains.interlocking
local ildb = advtrains.interlocking.db
local ilrs = advtrains.interlocking.route
@@ -14,6 +20,7 @@ local lntrans = { "A", "B" }
local function sigd_to_string(sigd)
return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s]
end
+advtrains.interlocking.sigd_to_string = sigd_to_string
minetest.register_node("advtrains_interlocking:tcb_node", {
drawtype = "mesh",
@@ -26,7 +33,7 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
},
mesh = "at_il_tcb_node.obj",
tiles = {"at_il_tcb_node.png"},
- description="Track Circuit Break",
+ description=S("Track Circuit Break"),
sunlight_propagates=true,
groups = {
cracky=3,
@@ -36,12 +43,12 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
},
after_place_node = function(pos, node, player)
local meta = minetest.get_meta(pos)
- meta:set_string("infotext", "Unconfigured Track Circuit Break, right-click to assign.")
+ meta:set_string("infotext", S("Unconfigured Track Circuit Break, right-click to assign."))
end,
on_rightclick = function(pos, node, player)
local pname = player:get_player_name()
if not minetest.check_player_privs(pname, "interlocking") then
- minetest.chat_send_player(pname, "Insufficient privileges to use this!")
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
return
end
@@ -53,11 +60,11 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
if tcb then
advtrains.interlocking.show_tcb_form(tcbpos, pname)
else
- minetest.chat_send_player(pname, "This TCB has been removed. Please dig marker.")
+ minetest.chat_send_player(pname, S("This TCB has been removed. Please dig marker."))
end
else
--unconfigured
- minetest.chat_send_player(pname, "Configuring TCB: Please punch the rail you want to assign this TCB to.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Please punch the rail you want to assign this TCB to."))
players_assign_tcb[pname] = pos
end
@@ -81,19 +88,15 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
local tcbpts = meta:get_string("tcb_pos")
if tcbpts ~= "" then
if not minetest.check_player_privs(pname, "interlocking") then
- minetest.chat_send_player(pname, "Insufficient privileges to use this!")
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
return
end
local tcbpos = minetest.string_to_pos(tcbpts)
local tcb = ildb.get_tcb(tcbpos)
if not tcb then return true end
for connid=1,2 do
- if tcb[connid].ts_id or tcb[connid].signal then
- minetest.chat_send_player(pname, "Can't remove TCB: Both sides must have no track section and no signal assigned!")
- return false
- end
- if not ildb.may_modify_tcbs(tcb[connid]) then
- minetest.chat_send_player(pname, "Can't remove TCB: Side "..connid.." forbids modification (shouldn't happen).")
+ if tcb[connid].signal then
+ minetest.chat_send_player(pname, S("Can't remove TCB: Both sides must have no signal assigned!"))
return false
end
end
@@ -102,18 +105,11 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, player)
if not oldmetadata or not oldmetadata.fields then return end
+ local pname = player:get_player_name()
local tcbpts = oldmetadata.fields.tcb_pos
if tcbpts and tcbpts ~= "" then
local tcbpos = minetest.string_to_pos(tcbpts)
- local success = ildb.remove_tcb(tcbpos)
- if success and player then
- minetest.chat_send_player(player:get_player_name(), "TCB has been removed.")
- else
- minetest.chat_send_player(player:get_player_name(), "Failed to remove TCB!")
- minetest.set_node(pos, oldnode)
- local meta = minetest.get_meta(pos)
- meta:set_string("tcb_pos", minetest.pos_to_string(tcbpos))
- end
+ ildb.remove_tcb_at(tcbpos, pname)
end
end,
})
@@ -165,26 +161,25 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
local tcbnpos = players_assign_tcb[pname]
if tcbnpos then
if vector.distance(pos, tcbnpos)<=20 then
- local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)
+ local node_ok, conns, rhe = advtrains.get_rail_info_at(pos)
if node_ok and #conns == 2 then
- local ok = ildb.create_tcb(pos)
-
- if not ok then
- minetest.chat_send_player(pname, "Configuring TCB: TCB already exists at this position! It has now been re-assigned.")
+ -- if there is already a tcb here, reassign it
+ if ildb.get_tcb(pos) then
+ minetest.chat_send_player(pname, S("Configuring TCB: Already existed at this position, it is now linked to this TCB marker"))
+ else
+ ildb.create_tcb_at(pos, pname)
end
-
- ildb.sync_tcb_neighbors(pos, 1)
- ildb.sync_tcb_neighbors(pos, 2)
-
+
local meta = minetest.get_meta(tcbnpos)
meta:set_string("tcb_pos", minetest.pos_to_string(pos))
- meta:set_string("infotext", "TCB assigned to "..minetest.pos_to_string(pos))
- minetest.chat_send_player(pname, "Configuring TCB: Successfully configured TCB")
+ meta:set_string("infotext", S("TCB assigned to @1", minetest.pos_to_string(pos)))
+ minetest.chat_send_player(pname, S("Configuring TCB: Successfully configured TCB"))
+ advtrains.interlocking.show_tcb_marker(pos)
else
- minetest.chat_send_player(pname, "Configuring TCB: This is not a normal two-connection rail! Aborted.")
+ minetest.chat_send_player(pname, S("Configuring TCB: This is not a normal two-connection rail! Aborted."))
end
else
- minetest.chat_send_player(pname, "Configuring TCB: Node is too far away. Aborted.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Node is too far away. Aborted."))
end
players_assign_tcb[pname] = nil
end
@@ -196,65 +191,225 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
local is_signal = minetest.get_item_group(node.name, "advtrains_signal") >= 2
if is_signal then
local ndef = minetest.registered_nodes[node.name]
- if ndef and ndef.advtrains and ndef.advtrains.set_aspect then
+ if ndef and ndef.advtrains and ndef.advtrains.apply_aspect then
local tcbs = ildb.get_tcbs(sigd)
if tcbs then
- tcbs.signal = pos
- 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
- ildb.set_sigd_for_signal(pos, sigd)
- minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.")
+ ildb.assign_signal_to_tcbs(pos, sigd)
+ -- use auto-naming
+ advtrains.interlocking.add_autoname_to_tcbs(tcbs, pname)
+ minetest.chat_send_player(pname, S("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.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Internal error, TCBS doesn't exist. Aborted."))
end
else
- minetest.chat_send_player(pname, "Configuring TCB: Cannot use static signals for routesetting. Aborted.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Cannot use static signals for routesetting. Aborted."))
end
else
- minetest.chat_send_player(pname, "Configuring TCB: Not a compatible signal. Aborted.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Not a compatible signal. Aborted."))
end
else
- minetest.chat_send_player(pname, "Configuring TCB: Node is too far away. Aborted.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Node is too far away. Aborted."))
end
players_assign_signal[pname] = nil
end
+
+ -- FixedLocks assignment
+ local ts_id = players_assign_fixedlocks[pname]
+ if ts_id then
+ if advtrains.is_passive(pos) then
+ local pts = advtrains.encode_pos(pos)
+ local state = advtrains.getstate(pos)
+ local ts = ildb.get_ts(ts_id)
+ if ts and ts.fixed_locks then
+ minetest.chat_send_player(pname, S("@1 locks in state @2", minetest.pos_to_string(pos), state))
+ ts.fixed_locks[pts] = state
+ else
+ minetest.chat_send_player(pname, S("Error: TS modified, abort!"))
+ players_assign_fixedlocks[pname] = nil
+ end
+ else
+ minetest.chat_send_player(pname, S("Setting fixed locks finished!"))
+ players_assign_fixedlocks[pname] = nil
+ ildb.update_rs_cache(ts_id)
+ advtrains.interlocking.show_ts_form(ts_id, pname)
+ end
+ end
end)
+-- "Self-contained TCB"
+-- 2024-11-25: Buffers should become their own TCB (and signal) automatically to permit setting routes to them
+-- These are support functions for this kind of node.
+
+-- Create an after_place_node callback for a self-contained TCB node. The parameters control additional behavior:
+-- fail_silently_on_noprivs: (boolean) Does not give an error in case the placer does not have the interlocking privilege
+-- auto_create_self_signal: (boolean) Automatically assign this same node as signal to the A side of the newly-created TCB
+-- (this is useful for buffers as they serve both as TCB and as an always-halt signal)
+function advtrains.interlocking.self_tcb_make_after_place_callback(fail_silently_on_noprivs, auto_create_self_signal)
+ return function(pos, player, itemstack, pointed_thing)
+ local pname = player:get_player_name()
+ if not minetest.check_player_privs(pname, "interlocking") then
+ if not fail_silently_on_noprivs then
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
+ end
+ return
+ end
+ if ildb.get_tcb(pos) then
+ minetest.chat_send_player(pname, S("TCB already existed at this position, now linked to this node"))
+ else
+ ildb.create_tcb_at(pos, pname)
+ end
+ if auto_create_self_signal then
+ local sigd = { p = pos, s = 1 }
+ local tcbs = ildb.get_tcbs(sigd)
+ -- make sure signal doesn't already exist
+ if tcbs.signal then
+ minetest.chat_send_player(pname, S("Signal on B side already assigned!"))
+ return
+ end
+ ildb.assign_signal_to_tcbs(pos, sigd)
+ -- assign influence point to itself
+ ildb.set_ip_signal(advtrains.roundfloorpts(pos), 1, pos)
+ -- use auto-naming
+ advtrains.interlocking.add_autoname_to_tcbs(tcbs, pname)
+ end
+ end
+end
+
+-- Create an can_dig callback for a self-contained TCB node. The parameters control additional behavior:
+-- is_signal: (boolean) Whether this node is also a signal (in addition to being a TCB), e.g. when auto_create_self_signal was set.
+-- Causes also the signal API's can_dig to be called
+function advtrains.interlocking.self_tcb_make_can_dig_callback(is_signal)
+ return function(pos, player)
+ local pname = player and player:get_player_name() or ""
+ -- need to duplicate logic of the regular "can_dig_or_modify_track()" function in core/tracks.lua
+ if advtrains.get_train_at_pos(pos) then
+ minetest.chat_send_player(pname, S("Can't remove track, a train is here!"))
+ return false
+ end
+ -- end of standard checks
+ local tcb = ildb.get_tcb(pos)
+ if not tcb then
+ -- digging always allowed because the TCB hasn't been created (unless signal callback interjects)
+ if is_signal then
+ return advtrains.interlocking.signal.can_dig(pos, player)
+ else
+ return true
+ end
+ end
+ -- TCB exists
+ if not minetest.check_player_privs(pname, "interlocking") then
+ return false
+ end
+ -- fine to remove (unless signal callback interjects)
+ if is_signal then
+ return advtrains.interlocking.signal.can_dig(pos, player)
+ else
+ return true
+ end
+ end
+end
+
+-- Create an after_dig_node callback for a self-contained TCB node. The parameters control additional behavior:
+-- is_signal: (boolean) Whether this node is also a signal (in addition to being a TCB), e.g. when auto_create_self_signal was set.
+-- Causes also the signal API's after_dig_node to be called
+function advtrains.interlocking.self_tcb_make_after_dig_callback(is_signal)
+ return function(pos, oldnode, oldmetadata, player)
+ local pname = player:get_player_name()
+ if is_signal then
+ -- "dig" the signal first
+ advtrains.interlocking.signal.after_dig(pos, oldnode, oldmetadata, player)
+ end
+ if ildb.get_tcb(pos) then
+ -- remove the TCB
+ ildb.remove_tcb_at(pos, pname, true)
+ end
+ end
+end
+
+-- Create an on_rightclick callback for a self-contained TCB node. The rightclick callback tries to repeat the TCB assignment
+-- if necessary and otherwise shows the TCB formspec. The parameters control additional behavior:
+-- fail_silently_on_noprivs: (boolean) Does not give an error in case the placer does not have the interlocking privilege
+-- auto_create_self_signal: (boolean) Automatically assign this same node as signal to the B side of the
+-- newly-created TCB if that has not already happened during place.
+-- Otherwise, opens the signal dialog instead of the TCB dialog on rightclick
+function advtrains.interlocking.self_tcb_make_on_rightclick_callback(fail_silently_on_noprivs, auto_create_self_signal)
+ return function(pos, node, player, itemstack, pointed_thing)
+ local pname = player:get_player_name()
+ if not minetest.check_player_privs(pname, "interlocking") then
+ if not fail_silently_on_noprivs then
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
+ end
+ return
+ end
+ if ildb.get_tcb(pos) then
+ -- TCB already here. go on
+ else
+ -- otherwise create tcb
+ ildb.create_tcb_at(pos, pname)
+ end
+ if auto_create_self_signal then
+ local sigd = { p = pos, s = 1 }
+ local tcbs = ildb.get_tcbs(sigd)
+ -- make sure signal doesn't already exist
+ if not tcbs.signal then
+ -- go ahead and assign signal
+ ildb.assign_signal_to_tcbs(pos, sigd)
+ -- assign influence point to itself
+ ildb.set_ip_signal(advtrains.roundfloorpts(pos), 1, pos)
+ -- use auto-naming
+ advtrains.interlocking.add_autoname_to_tcbs(tcbs, pname)
+ end
+ -- in any case open the signalling form nouw
+ local control = player:get_player_control()
+ advtrains.interlocking.show_signal_form(pos, node, pname, control.aux1)
+ return
+ else
+ -- not an autosignal. Then show the TCB form
+ advtrains.interlocking.show_tcb_form(pos, pname)
+ return
+ end
+ end
+end
+
-- TCB Form
-local function mktcbformspec(tcbs, btnpref, offset, pname)
+local function mktcbformspec(pos, side, tcbs, offset, pname)
local form = ""
+ local btnpref = side==1 and "A" or "B"
local ts
+ -- ensure that mapping and xlink are up to date
+ ildb.tcbs_ensure_ts_ref_exists({p=pos, s=side, tcbs=tcbs})
+ ildb.validate_tcb_xlink({p=pos, s=side, tcbs=tcbs})
+ -- Note: repair operations may have been triggered by this
if tcbs.ts_id then
ts = ildb.get_ts(tcbs.ts_id)
end
if ts then
- form = form.."label[0.5,"..offset..";Side "..btnpref..": "..minetest.formspec_escape(ts.name).."]"
- form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_gotots;Show track section]"
- if ildb.may_modify_tcbs(tcbs) then
- -- Note: the security check to prohibit those actions is located in database.lua in the corresponding functions.
- form = form.."button[0.5,"..(offset+1.5)..";2.5,1;"..btnpref.."_update;Update near TCBs]"
- form = form.."button[3 ,"..(offset+1.5)..";2.5,1;"..btnpref.."_remove;Remove from section]"
- end
+ form = form.."label[0.5,"..offset..";"..S("Side @1", btnpref)..": "..minetest.formspec_escape(ts.name or tcbs.ts_id).."]"
+ form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_gotots;"..S("Show track section").."]"
else
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
+ form = form.."label[0.5,"..offset..";Side "..btnpref..": "..S("End of interlocking").."]"
+ form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_makeil;"..S("Create Interlocked Track Section").."]"
+ end
+ -- xlink
+ if tcbs.xlink then
+ form = form.."label[0.5,"..(offset+1.5)..";"..S("Link: @1", ildb.sigd_to_string(tcbs.xlink)).."]"
+ form = form.."button[4.5,"..(offset+1.5)..";1,1;"..btnpref.."_xlinkdel;X]"
+ else
+ if players_assign_xlink[pname] then
+ form = form.."button[0.5,"..(offset+1.5)..";4,1;"..btnpref.."_xlinklink;"..S("Link @1", ildb.sigd_to_string(players_assign_xlink[pname])).."]"
+ form = form.."button[4.5,"..(offset+1.5)..";1,1;"..btnpref.."_xlinkabrt;X]"
+ else
+ form = form.."label[0.5,"..(offset+1.5)..";"..S("No Link").."]"
+ form = form.."button[4.5,"..(offset+1.5)..";1,1;"..btnpref.."_xlinkadd;+]"
+ end
end
if tcbs.signal then
- form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_sigdia;Signalling]"
+ form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_sigdia;"..S("Signalling").."]"
else
- form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_asnsig;Assign a signal]"
+ form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_asnsig;"..S("Assign a signal").."]"
end
return form
end
@@ -262,15 +417,15 @@ end
function advtrains.interlocking.show_tcb_form(pos, pname)
if not minetest.check_player_privs(pname, "interlocking") then
- minetest.chat_send_player(pname, "Insufficient privileges to use this!")
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
return
end
local tcb = ildb.get_tcb(pos)
if not tcb then return end
- local form = "size[6,9] label[0.5,0.5;Track Circuit Break Configuration]"
- form = form .. mktcbformspec(tcb[1], "A", 1, pname)
- form = form .. mktcbformspec(tcb[2], "B", 5, pname)
+ local form = "size[6,9] label[0.5,0.5;"..S("Track Circuit Break Configuration").."]"
+ form = form .. mktcbformspec(pos, 1, tcb[1], 1, pname)
+ form = form .. mktcbformspec(pos, 2, tcb[2], 5, pname)
minetest.show_formspec(pname, "at_il_tcbconfig_"..minetest.pos_to_string(pos), form)
advtrains.interlocking.show_tcb_marker(pos)
@@ -297,13 +452,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local tcb = ildb.get_tcb(pos)
if not tcb then return end
local f_gotots = {fields.A_gotots, fields.B_gotots}
- local f_update = {fields.A_update, fields.B_update}
- local f_remove = {fields.A_remove, fields.B_remove}
local f_makeil = {fields.A_makeil, fields.B_makeil}
- local f_setlocked = {fields.A_setlocked, fields.B_setlocked}
- local f_setfree = {fields.A_setfree, fields.B_setfree}
local f_asnsig = {fields.A_asnsig, fields.B_asnsig}
local f_sigdia = {fields.A_sigdia, fields.B_sigdia}
+ local f_xlinkadd = {fields.A_xlinkadd, fields.B_xlinkadd}
+ local f_xlinkdel = {fields.A_xlinkdel, fields.B_xlinkdel}
+ local f_xlinklink = {fields.A_xlinklink, fields.B_xlinklink}
+ local f_xlinkabrt = {fields.A_xlinkabrt, fields.B_xlinkabrt}
for connid=1,2 do
local tcbs = tcb[connid]
@@ -312,32 +467,37 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
advtrains.interlocking.show_ts_form(tcbs.ts_id, pname)
return
end
- if f_update[connid] then
- ildb.sync_tcb_neighbors(pos, connid)
- end
- if f_remove[connid] then
- ildb.remove_from_interlocking({p=pos, s=connid})
- end
else
if f_makeil[connid] then
- -- try sinc_tcb_neighbors first
- ildb.sync_tcb_neighbors(pos, connid)
- -- if that didn't work, create new section
if not tcbs.ts_id then
- ildb.create_ts({p=pos, s=connid})
- ildb.sync_tcb_neighbors(pos, connid)
+ ildb.create_ts_from_tcbs({p=pos, s=connid})
end
end
- -- non-interlocked
- if f_setfree[connid] then
- tcbs.section_free = true
+ end
+ if tcbs.xlink then
+ if f_xlinkdel[connid] then
+ ildb.remove_tcb_xlink({p=pos, s=connid})
end
- if f_setlocked[connid] then
- tcbs.section_free = nil
+ else
+ local osigd = players_assign_xlink[pname]
+ if osigd then
+ if f_xlinklink[connid] then
+ ildb.add_tcb_xlink({p=pos, s=connid}, osigd)
+ players_assign_xlink[pname] = nil
+ elseif f_xlinkabrt[connid] then
+ players_assign_xlink[pname] = nil
+ end
+ else
+ if f_xlinkadd[connid] then
+ players_assign_xlink[pname] = {p=pos, s=connid}
+ minetest.chat_send_player(pname, S("TCB Link: Select linked TCB now!"))
+ minetest.close_formspec(pname, formname)
+ return -- to not reopen form
+ end
end
end
if f_asnsig[connid] and not tcbs.signal then
- minetest.chat_send_player(pname, "Configuring TCB: Please punch the signal to assign.")
+ minetest.chat_send_player(pname, S("Configuring TCB: Please punch the signal to assign."))
players_assign_signal[pname] = {p=pos, s=connid}
minetest.close_formspec(pname, formname)
return
@@ -357,20 +517,17 @@ end)
-- TS Formspec
--- textlist selection temporary storage
-local ts_pselidx = {}
-
-function advtrains.interlocking.show_ts_form(ts_id, pname, sel_tcb)
+function advtrains.interlocking.show_ts_form(ts_id, pname)
if not minetest.check_player_privs(pname, "interlocking") then
- minetest.chat_send_player(pname, "Insufficient privileges to use this!")
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
return
end
local ts = ildb.get_ts(ts_id)
if not ts_id then return end
- local form = "size[10,10]label[0.5,0.5;Track Section Detail - "..ts_id.."]"
- form = form.."field[0.8,2;5.2,1;name;Section name;"..minetest.formspec_escape(ts.name).."]"
- form = form.."button[5.5,1.7;1,1;setname;Set]"
+ local form = "size[10.5,10]label[0.5,0.5;"..S("Track Section Detail - @1", ts_id).."]"
+ form = form.."field[0.8,2;5.2,1;name;"..S("Section name")..";"..minetest.formspec_escape(ts.name or "").."]"
+ form = form.."button[5.5,1.7;1,1;setname;"..S("Set").."]"
local hint
local strtab = {}
@@ -379,58 +536,51 @@ function advtrains.interlocking.show_ts_form(ts_id, pname, sel_tcb)
advtrains.interlocking.show_tcb_marker(sigd.p)
end
- form = form.."textlist[0.5,3;5,3;tcblist;"..table.concat(strtab, ",").."]"
+ form = form.."label[0.5,2.5;"..S("Boundary TCBs:").."]"
+ form = form.."textlist[0.5,3;4,3;tcblist;"..table.concat(strtab, ",").."]"
+
+ -- additional route locks (e.g. for level crossings)
+
+ strtab = {}
+ if ts.fixed_locks then
+ for pts, state in pairs(ts.fixed_locks) do
+ strtab[#strtab+1] = minetest.formspec_escape(
+ minetest.pos_to_string(advtrains.decode_pos(pts)).." = "..state)
+ end
+ end
+ form = form.."label[5.5,2.5;"..S("Fixed route locks (e.g. level crossings):").."]"
+ form = form.."textlist[5.5,3;4,3;fixedlocks;"..table.concat(strtab, ",").."]"
if ildb.may_modify_ts(ts) then
+ form = form.."button[5.5,6;2,1;flk_add;"..S("Add locks").."]"
+ form = form.."button[7.5,6;2,1;flk_clear;"..S("Clear locks").."]"
- if players_link_ts[pname] then
- local other_id = players_link_ts[pname]
- local other_ts = ildb.get_ts(other_id)
- if other_ts then
- if ildb.may_modify_ts(other_ts) then
- form = form.."button[5.5,3;3.5,1;mklink;Join with "..minetest.formspec_escape(other_ts.name).."]"
- form = form.."button[9 ,3;0.5,1;cancellink;X]"
- end
- end
- else
- form = form.."button[5.5,3;4,1;link;Join into other section]"
- hint = 1
- end
- form = form.."button[5.5,4;4,1;dissolve;Dissolve Section]"
- form = form.."tooltip[dissolve;This will remove the track section and set all its end points to End Of Interlocking]"
- if sel_tcb then
- form = form.."button[5.5,5;4,1;del_tcb;Unlink selected TCB]"
- hint = 2
- end
+ form = form.."button[5.5,8;4,1;remove;"..S("Remove Section").."]"
+ form = form.."tooltip[remove;"..S("This will remove the track section and set all its end points to End Of Interlocking").."]"
else
hint=3
end
if ts.route then
- form = form.."label[0.5,6.1;Route is set: "..ts.route.rsn.."]"
+ form = form.."label[0.5,6.1;"..S("Route is set: ")..ts.route.rsn.."]"
elseif ts.route_post then
- form = form.."label[0.5,6.1;Section holds "..#(ts.route_post.lcks or {}).." route locks.]"
+ form = form.."label[0.5,6.1;"..S("Section holds @1 route locks.", #(ts.route_post.lcks or {})).."]"
end
-- occupying trains
if ts.trains and #ts.trains>0 then
- form = form.."label[0.5,7.1;Trains on this section:]"
+ form = form.."label[0.5,7.1;"..S("Trains on this section:").."]"
form = form.."textlist[0.5,7.7;3,2;trnlist;"..table.concat(ts.trains, ",").."]"
else
- form = form.."label[0.5,7.1;No trains on this section.]"
+ form = form.."label[0.5,7.1;"..S("No trains on this section.").."]"
end
- form = form.."button[5.5,7;4,1;reset;Reset section state]"
-
- if hint == 1 then
- form = form.."label[0.5,0.75;Use the 'Join' button to designate rail crosses and link not listed far-away TCBs]"
- elseif hint == 2 then
- form = form.."label[0.5,0.75;Unlinking a TCB will set it to non-interlocked mode.]"
- elseif hint == 3 then
- form = form.."label[0.5,0.75;You cannot modify track sections when a route is set or a train is on the section.]"
+ form = form.."button[5.5,7;4,1;reset;"..S("Reset section state").."]"
+
+ if hint == 3 then
+ form = form.."label[0.5,0.75;"..S("You cannot modify track sections when a route is set or a train is on the section.").."]"
--form = form.."label[0.5,1;Trying to unlink a TCB directly connected to this track will not work.]"
end
- ts_pselidx[pname]=sel_tcb
minetest.show_formspec(pname, "at_il_tsconfig_"..ts_id, form)
end
@@ -442,45 +592,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return
end
-- independent of the formspec, clear this whenever some formspec event happens
- local tpsi = ts_pselidx[pname]
- ts_pselidx[pname] = nil
local ts_id = string.match(formname, "^at_il_tsconfig_(.+)$")
if ts_id and not fields.quit then
local ts = ildb.get_ts(ts_id)
if not ts then return end
- local sel_tcb
- if fields.tcblist then
- local tev = minetest.explode_textlist_event(fields.tcblist)
- sel_tcb = tev.index
- ts_pselidx[pname] = sel_tcb
- elseif tpsi then
- sel_tcb = tpsi
- end
-
if ildb.may_modify_ts(ts) then
- if players_link_ts[pname] then
- if fields.cancellink then
- players_link_ts[pname] = nil
- elseif fields.mklink then
- ildb.link_track_sections(players_link_ts[pname], ts_id)
- players_link_ts[pname] = nil
- end
- end
-
- if fields.del_tcb and sel_tcb and sel_tcb > 0 and sel_tcb <= #ts.tc_breaks then
- if not ildb.remove_from_interlocking(ts.tc_breaks[sel_tcb]) then
- minetest.chat_send_player(pname, "Please unassign signal first!")
- end
- sel_tcb = nil
- end
-
- if fields.link then
- players_link_ts[pname] = ts_id
- end
- if fields.dissolve then
- ildb.dissolve_ts(ts_id)
+ if fields.remove then
+ ildb.remove_ts(ts_id)
minetest.close_formspec(pname, formname)
return
end
@@ -489,17 +609,29 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.setname then
ts.name = fields.name
if ts.name == "" then
- ts.name = "Section "..ts_id
+ ts.name = nil
end
end
+ if fields.flk_add then
+ if not ts.fixed_locks then
+ ts.fixed_locks = {}
+ end
+ players_assign_fixedlocks[pname] = ts_id
+ minetest.chat_send_player(pname, S("Punch components to add fixed locks. (punch anything else = end)"))
+ minetest.close_formspec(pname, formname)
+ return
+ elseif fields.flk_clear then
+ ts.fixed_locks = nil
+ end
+
if fields.reset then
-- User requested resetting the section
-- Show him what this means...
- local form = "size[7,5]label[0.5,0.5;Reset track section]"
- form = form.."label[0.5,1;This will clear the list of trains\nand the routesetting status of this section.\nAre you sure?]"
- form = form.."button_exit[0.5,2.5; 5,1;reset;Yes]"
- form = form.."button_exit[0.5,3.5; 5,1;cancel;Cancel]"
+ local form = "size[7,5]label[0.5,0.5;"..S("Reset track section").."]"
+ form = form.."label[0.5,1;"..S("This will clear the list of trains\nand the routesetting status of this section.\nAre you sure?").."]"
+ form = form.."button_exit[0.5,2.5; 5,1;reset;"..S("Yes").."]"
+ form = form.."button_exit[0.5,3.5; 5,1;cancel;"..S("Cancel").."]"
minetest.show_formspec(pname, "at_il_tsreset_"..ts_id, form)
return
end
@@ -520,9 +652,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
ts.route = nil
for _, sigd in ipairs(ts.tc_breaks) do
local tcbs = ildb.get_tcbs(sigd)
- advtrains.interlocking.update_signal_aspect(tcbs)
+ advtrains.interlocking.signal.update_route_aspect(tcbs)
end
- minetest.chat_send_player(pname, "Reset track section "..ts_id.."!")
+ minetest.chat_send_player(pname, S("Reset track section @1!", ts_id))
end
end)
@@ -573,7 +705,7 @@ function advtrains.interlocking.show_tcb_marker(pos)
ts = ildb.get_ts(tcbs.ts_id)
end
if ts then
- itex[connid] = ts.name
+ itex[connid] = ts.name or tcbs.ts_id or "???"
else
itex[connid] = "--EOI--"
end
@@ -594,6 +726,92 @@ function advtrains.interlocking.show_tcb_marker(pos)
markerent[pts] = obj
end
+function advtrains.interlocking.remove_tcb_marker(pos)
+ local pts = advtrains.roundfloorpts(pos)
+ if markerent[pts] then
+ markerent[pts]:remove()
+ end
+ markerent[pts] = nil
+end
+
+local ts_showparticles_callback = function(pos, connid, bconnid)
+ minetest.add_particle({
+ pos = pos,
+ velocity = {x=0, y=0, z=0},
+ acceleration = {x=0, y=0, z=0},
+ expirationtime = 10,
+ size = 7,
+ vertical = true,
+ texture = "at_il_ts_highlight_particle.png",
+ glow = 6,
+ })
+end
+
+-- Spawns particles to highlight the clicked track section
+-- TODO: Adapt behavior to not dumb-walk anymore
+function advtrains.interlocking.highlight_track_section(pos)
+ local all_tcbs = ildb.get_all_tcbs_adjacent(pos, nil, ts_showparticles_callback)
+ for _,sigd in ipairs(all_tcbs) do
+ advtrains.interlocking.show_tcb_marker(sigd.p)
+ end
+end
+
+-- checks that the given route is still valid (i.e. all its TCBs, sections and locks exist)
+-- returns true (ok) or false, reason (on issue)
+function advtrains.interlocking.check_route_valid(route, sigd)
+ -- this code is partially copy-pasted from routesetting.lua
+ -- we start at the tc designated by signal
+ local c_sigd = sigd
+ local i = 1
+ local c_tcbs, c_ts_id, c_ts, c_rseg
+ while c_sigd and i<=#route do
+ c_tcbs = ildb.get_tcbs(c_sigd)
+ if not c_tcbs then
+ return false, S("TCB at @1 is missing", sigd_to_string(c_sigd))
+ end
+ c_ts_id = c_tcbs.ts_id
+ if not c_ts_id then
+ return false, S("Track section after @1 missing", sigd_to_string(c_sigd))
+ end
+ c_ts = ildb.get_ts(c_ts_id)
+
+ c_rseg = route[i]
+
+ if c_rseg.locks then
+ for pts, state in pairs(c_rseg.locks) do
+ local pos = advtrains.decode_pos(pts)
+ if not advtrains.is_passive(pos) then
+ return false, S("Turnout/component missing at @1", minetest.pos_to_string(pos))
+ end
+ end
+ end
+ -- sanity check, is section at next the same as the current?
+ local nvar = c_rseg.next
+ if nvar then
+ local re_tcbs = ildb.get_tcbs({p = nvar.p, s = (nvar.s==1) and 2 or 1})
+ if not re_tcbs then
+ return false, S("TCB at @1 is missing", minetest.pos_to_string(nvar.p))
+ elseif not re_tcbs.ts_id then
+ return false, S("TCB at @1 is not assigned to previous track section", minetest.pos_to_string(nvar.p))
+ elseif re_tcbs.ts_id~=c_ts_id then
+ return false, S("TCB at @1 has different section than previous TCB", minetest.pos_to_string(nvar.p))
+ end
+ end
+ -- advance
+ c_sigd = nvar
+ i = i + 1
+ end
+ -- check end TCB
+ if not c_sigd then
+ return false, S("Final TCBS unset (legacy-style buffer route)")
+ end
+ c_tcbs = ildb.get_tcbs(c_sigd)
+ if not c_tcbs then
+ return false, S("TCB at @1 is missing", sigd_to_string(c_sigd))
+ end
+ return true, nil, c_sigd
+end
+
-- Signalling formspec - set routes a.s.o
-- textlist selection temporary storage
@@ -603,90 +821,137 @@ local p_open_sig_form = {}
function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, called_from_form_update)
if not minetest.check_player_privs(pname, "train_operator") then
- minetest.chat_send_player(pname, "Insufficient privileges to use this!")
+ minetest.chat_send_player(pname, S("Insufficient privileges to use this!"))
return
end
local hasprivs = minetest.check_player_privs(pname, "interlocking")
local tcbs = ildb.get_tcbs(sigd)
if not tcbs.signal then return end
- 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,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;"..minetest.formspec_escape(tcbs.signal_name).."]"
- form = form.."button[5.5,1.2;1,1;setname;Set]"
+ local form = "size[7,10.25]label[0.5,0.5;"..S("Signal at @1", minetest.pos_to_string(sigd.p)).."]"
+ form = form.."field[0.8,1.5;5.2,1;name;"..S("Signal name")..";"..minetest.formspec_escape(tcbs.signal_name or "").."]"
+ form = form.."button[5.5,1.2;1,1;setname;"..S("Set").."]"
if tcbs.routeset then
- local rte = tcbs.routes[tcbs.routeset]
- if not rte then
- atwarn("Unknown route set from signal!")
- tcbs.routeset = nil
- return
+ if type(tcbs.routeset)=="table" then
+ local rtenames = {}
+ for midx,rteid in ipairs(tcbs.routeset) do
+ local rte = tcbs.routes[rteid]
+ if not rte then
+ atwarn("Unknown route set from signal!")
+ tcbs.routeset = nil
+ return
+ end
+ rtenames[midx] = rte.name
+ end
+ form = form.."label[0.5,2.5;"..S("Multiple routes are requested (first available is set):").."]"
+ form = form.."label[0.5,3.0;"..minetest.formspec_escape(table.concat(rtenames,", ")).."]"
+ else
+ local rte = tcbs.routes[tcbs.routeset]
+ if not rte then
+ atwarn("Unknown route set from signal!")
+ tcbs.routeset = nil
+ return
+ end
+ form = form.."label[0.5,2.5;"..S("A route is requested from this signal:").."]"
+ form = form.."label[0.5,3.0;"..minetest.formspec_escape(rte.name).."]"
end
- form = form.."label[0.5,2.5;A route is requested from this signal:]"
- form = form.."label[0.5,3.0;"..minetest.formspec_escape(rte.name).."]"
if tcbs.route_committed then
- form = form.."label[0.5,3.5;Route has been set.]"
+ form = form.."label[0.5,3.5;"..S("Route has been set.").."]"
else
- form = form.."label[0.5,3.5;Waiting for route to be set...]"
+ form = form.."label[0.5,3.5;"..S("Waiting for route to be set...").."]"
if tcbs.route_rsn then
form = form.."label[0.5,4;"..minetest.formspec_escape(tcbs.route_rsn).."]"
end
end
if not tcbs.route_auto then
- form = form.."button[0.5,7; 5,1;auto;Enable Automatic Working]"
+ form = form.."button[0.5,7; 5,1;auto;"..S("Enable Automatic Working").."]"
else
- form = form.."label[0.5,7 ;Automatic Working is active.]"
- form = form.."label[0.5,7.3;Route is re-set when a train passed.]"
- form = form.."button[0.5,7.7; 5,1;noauto;Disable Automatic Working]"
+ form = form.."label[0.5,7 ;"..S("Automatic Working is active.").."]"
+ form = form.."label[0.5,7.3;"..S("Route is re-set when a train passed.").."]"
+ form = form.."button[0.5,7.7; 5,1;noauto;"..S("Disable Automatic Working").."]"
end
- form = form.."button[0.5,6; 5,1;cancelroute;Cancel Route]"
+ form = form.."button[0.5,6; 5,1;cancelroute;"..S("Cancel Route").."]"
else
if not tcbs.route_origin then
- local strtab = {}
- for idx, route in ipairs(tcbs.routes) do
- local clr = ""
- if route.ars then
- clr = "#FF5555"
- if route.ars.default then
- clr = "#55FF55"
+ if #tcbs.routes > 0 then
+ -- at least one route is defined, show normal dialog
+ local strtab = {}
+ for idx, route in ipairs(tcbs.routes) do
+ local rname = route.name
+ local valid = atil.check_route_valid(route, sigd)
+ local clr = ""
+ if not valid then
+ clr = "#FF5555"
+ rname = rname..S(" (invalid)")
+ elseif route.ars then
+ clr = "#FFFF55"
+ if route.ars.default then
+ clr = "#55FF55"
+ end
+ end
+ strtab[#strtab+1] = clr .. minetest.formspec_escape(rname)
+ end
+ form = form.."label[0.5,2.5;"..S("Routes:").."]"
+ form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",")
+ if sel_rte then
+ form = form .. ";" .. sel_rte .."]"
+ form = form.."button[0.5,6; 5,1;setroute;"..S("Set Route").."]"
+ form = form.."button[0.5,7;2,1;dsproute;"..S("Show").."]"
+ if hasprivs then
+ form = form.."button[5.5,3.3;1,0.3;setarsdefault;D]tooltip[setarsdefault;"..S("Set ARS default route").."]"
+ form = form.."button[3.5,7;2,1;editroute;"..S("Edit").."]"
+ if sel_rte > 1 then
+ form = form .. "button[5.5,4;1,0.3;moveup;↑]"
+ end
+ if sel_rte < #strtab then
+ form = form .. "button[5.5,4.7;1,0.3;movedown;↓]"
+ end
+ form = form.."button[5.5,5.4;1,0.3;delroute;X]tooltip[delroute;"..S("Delete this route").."]"
+ end
+ else
+ form = form .. "]"
+ if tcbs.ars_disabled then
+ form = form.."label[0.5,6 ;"..S("NOTE: ARS is disabled.").."]"
+ form = form.."label[0.5,6.5;"..S("Routes are not automatically set.").."]"
end
end
- strtab[#strtab+1] = clr .. minetest.formspec_escape(route.name)
- end
- form = form.."label[0.5,2.5;Routes:]"
- form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",").."]"
- if sel_rte then
- form = form.."button[0.5,6; 5,1;setroute;Set Route]"
- form = form.."button[0.5,7;2,1;dsproute;Show]"
if hasprivs then
- form = form.."button[3.5,7;2,1;editroute;Edit]"
+ form = form.."button[0.5,8;2.5,1;smartroute;"..S("Smart Route").."]"
+ form = form.."button[ 3,8;2.5,1;newroute;"..S("New (Manual)").."]"
+ form = form..string.format("checkbox[0.5,8.75;ars;"..S("Automatic routesetting")..";%s]", not tcbs.ars_disabled)
+ form = form..string.format("checkbox[0.5,9.25;dstarstrig;"..S("Distant signal triggers ARS")..";%s]", not tcbs.no_dst_ars_trig)
end
else
- if tcbs.ars_disabled then
- form = form.."label[0.5,6 ;NOTE: ARS is disabled.]"
- form = form.."label[0.5,6.5;Routes are not automatically set.]"
+ -- no route is active, and no route is so far defined
+ if not tcbs.signal then atwarn("signalling form missing signal?!", pos) return end -- safeguard, nothing else in this function checks tcbs.signal
+ local caps = advtrains.interlocking.signal.get_signal_cap_level(tcbs.signal)
+ if caps >= 4 then
+ -- offer user the "block signal mode"
+ form = form.."label[0.5,2.5;"..S("No routes are yet defined.").."]"
+ if hasprivs then
+ form = form.."button[0.5,4;2.5,1;smartroute;"..S("Smart Route").."]"
+ form = form.."button[ 3,4;2.5,1;newroute;"..S("New (Manual)").."]"
+ end
+ elseif caps >= 3 then
+ -- it's a buffer!
+ form = form.."label[0.5,2.5;"..S("This is an always-halt signal (e.g. a buffer)\nNo routes can be set from here.").."]"
+ else
+ -- signal caps say it cannot be route start/end
+ form = form.."label[0.5,2.5;"..S("This is a pure distant signal\nNo route is currently set through.").."]"
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
- if tcbs.ars_disabled then
- form = form.."button[0.5,9;2.5,1;arsenable;Enable ARS]"
- else
- form = form.."button[0.5,9;2.5,1;arsdisable;Disable ARS]"
- end
+
elseif sigd_equal(tcbs.route_origin, sigd) then
-- something has gone wrong: tcbs.routeset should have been set...
- form = form.."label[0.5,2.5;Inconsistent state: route_origin is same TCBS but no route set. Try again.]"
+ form = form.."label[0.5,2.5;".."Inconsistent state: route_origin is same TCBS but no route set. Try again.".."]"
ilrs.cancel_route_from(sigd)
else
- form = form.."label[0.5,2.5;Route is set over this signal by:\n"..sigd_to_string(tcbs.route_origin).."]"
- form = form.."label[0.5,4;Wait for this route to be cancelled in order to do anything here.]"
+ form = form.."label[0.5,2.5;"..S("Route is set over this signal by:").."\n"..sigd_to_string(tcbs.route_origin).."]"
+ form = form.."label[0.5,4;"..S("Wait for this route to be cancelled in order to do anything here.").."]"
end
end
sig_pselidx[pname] = sel_rte
@@ -696,14 +961,14 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle
-- always a good idea to update the signal aspect
if not called_from_form_update then
-- FIX prevent a callback loop
- advtrains.interlocking.update_signal_aspect(tcbs)
+ advtrains.interlocking.signal.update_route_aspect(tcbs)
end
end
function advtrains.interlocking.update_player_forms(sigd)
for pname, tsigd in pairs(p_open_sig_form) do
if advtrains.interlocking.sigd_equal(sigd, tsigd) then
- advtrains.interlocking.show_signalling_form(sigd, pname, nil)
+ advtrains.interlocking.show_signalling_form(sigd, pname, nil, true)
end
end
end
@@ -716,10 +981,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
local hasprivs = minetest.check_player_privs(pname, "interlocking")
- -- independent of the formspec, clear this whenever some formspec event happens
local tpsi = sig_pselidx[pname]
- sig_pselidx[pname] = nil
- p_open_sig_form[pname] = nil
local pts, connids = string.match(formname, "^at_il_signalling_([^_]+)_(%d)$")
local pos, connid
@@ -734,6 +996,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if not tcbs then return end
if fields.quit then
+ sig_pselidx[pname] = nil
+ p_open_sig_form[pname] = nil
-- form quit: disable temporary ARS ignore
tcbs.ars_ignore_next = nil
return
@@ -742,17 +1006,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local sel_rte
if fields.rtelist then
local tev = minetest.explode_textlist_event(fields.rtelist)
- sel_rte = tev.index
+ if tev.type ~= "INV" then
+ sel_rte = tev.index
+ end
elseif tpsi then
sel_rte = tpsi
end
if fields.setname and fields.name and hasprivs then
- tcbs.signal_name = fields.name
+ if fields.name == "" then
+ tcbs.signal_name = nil -- do not save a signal name if it isnt used (equivalent to track sections)
+ else
+ tcbs.signal_name = fields.name
+ end
end
if tcbs.routeset and fields.cancelroute then
- if tcbs.routes[tcbs.routeset] and tcbs.routes[tcbs.routeset].ars then
- tcbs.ars_ignore_next = true
- end
+ tcbs.ars_ignore_next = true
-- if route committed, cancel route ts info
ilrs.update_route(sigd, tcbs, nil, true)
end
@@ -761,6 +1029,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
advtrains.interlocking.init_route_prog(pname, sigd)
minetest.close_formspec(pname, formname)
tcbs.ars_ignore_next = nil
+ p_open_sig_form[pname] = nil -- form is closed/left, do not reopen
+ return
+ end
+ if fields.smartroute and hasprivs then
+ advtrains.interlocking.smartroute.start(pname, sigd)
+ tcbs.ars_ignore_next = nil
+ p_open_sig_form[pname] = nil -- form is closed/left, do not reopen
return
end
if sel_rte and tcbs.routes[sel_rte] then
@@ -774,39 +1049,46 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if fields.editroute and hasprivs then
advtrains.interlocking.show_route_edit_form(pname, sigd, sel_rte)
- --local rte = tcbs.routes[sel_rte]
- --minetest.show_formspec(pname, formname.."_renroute_"..sel_rte, "field[name;Enter new route name;"..rte.name.."]")
+ p_open_sig_form[pname] = nil -- form is closed/left, do not reopen
return
end
+ if fields.setarsdefault and hasprivs then
+ for rid, route in ipairs(tcbs.routes) do
+ local isdefault = rid == sel_rte
+ if route.ars then
+ if route.ars.default and isdefault then
+ -- D button pressed but route was already default - remove ars default field!
+ route.ars.default = nil
+ elseif isdefault then
+ route.ars.default = true
+ else
+ route.ars.default = nil
+ end
+ -- if the table is nouw empty delete it
+ if not next(route.ars) then
+ route.ars = nil
+ end
+ elseif isdefault then
+ route.ars = {default = true}
+ end
+ end
+ end
+ if fields.delroute and hasprivs then
+ if tcbs.routes[sel_rte] and tcbs.routes[sel_rte].ars then
+ minetest.chat_send_player(pname, S("Cannot delete route which has ARS rules, please review and then delete through edit dialog!"))
+ else
+ table.remove(tcbs.routes,sel_rte)
+ end
+ end
end
end
- if fields.unassign and hasprivs then
- -- unassigning the signal from the tcbs
- -- only when no route is set.
- -- Routes and name remain saved, in case the player wants to reassign a new signal
- if not tcbs.routeset then
- local signal_pos = tcbs.signal
- ildb.set_sigd_for_signal(signal_pos, nil)
- tcbs.signal = nil
- tcbs.aspect = nil
- minetest.close_formspec(pname, formname)
- minetest.chat_send_player(pname, "Signal has been unassigned. Name and routes are kept for reuse.")
- return
- else
- 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
+ if fields.ars then
+ tcbs.ars_disabled = not minetest.is_yes(fields.ars)
end
- if tcbs.ars_disabled and fields.arsenable then
- tcbs.ars_disabled = nil
- end
- if not tcbs.ars_disabled and fields.arsdisable then
- tcbs.ars_disabled = true
+ if fields.dstarstrig then
+ tcbs.no_dst_ars_trig = not minetest.is_yes(fields.dstarstrig)
end
if fields.auto then
@@ -815,28 +1097,22 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.noauto then
tcbs.route_auto = false
end
+
+ if sel_rte and tcbs.routes[sel_rte]and not tcbs.routeset then
+ if fields.moveup then
+ if tcbs.routes[sel_rte - 1] then
+ tcbs.routes[sel_rte - 1], tcbs.routes[sel_rte] = tcbs.routes[sel_rte], tcbs.routes[sel_rte - 1]
+ sel_rte = sel_rte - 1
+ end
+ elseif fields.movedown then
+ if tcbs.routes[sel_rte + 1] then
+ tcbs.routes[sel_rte + 1], tcbs.routes[sel_rte] = tcbs.routes[sel_rte], tcbs.routes[sel_rte + 1]
+ sel_rte = sel_rte + 1
+ end
+ end
+ end
advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, true)
return
end
-
-
- if not hasprivs then return end
- -- rename route
- local rind, rte_id
- pts, connids, rind = string.match(formname, "^at_il_signalling_([^_]+)_(%d)_renroute_(%d+)$")
- if pts then
- pos = minetest.string_to_pos(pts)
- connid = tonumber(connids)
- rte_id = tonumber(rind)
- if not connid or connid<1 or connid>2 then return end
- end
- if pos and connid and rind and fields.name then
- local sigd = {p=pos, s=connid}
- local tcbs = ildb.get_tcbs(sigd)
- if tcbs.routes[rte_id] then
- tcbs.routes[rte_id].name = fields.name
- advtrains.interlocking.show_signalling_form(sigd, pname)
- end
- end
end)