Connect the ropes, start on making the UI work
This commit is contained in:
parent
852da6bcae
commit
6fd845baec
|
@ -57,7 +57,7 @@ function advtrains.setstate(parpos, newstate, pnode)
|
|||
return false, "train_here"
|
||||
end
|
||||
|
||||
if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.encode_pos(pos)) then
|
||||
if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(advtrains.encode_pos(pos)) then
|
||||
return false, "route_lock_here"
|
||||
end
|
||||
|
||||
|
|
|
@ -1006,7 +1006,7 @@ end
|
|||
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)
|
||||
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)
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
--- Distant signaling.
|
||||
-- This module implements a database backend for distant signal assignments.
|
||||
-- The actual modifications to signal aspects are still done by signal aspect accessors.
|
||||
-- @module advtrains.interlocking.distant
|
||||
|
||||
local db_distant = {}
|
||||
local db_distant_of = {}
|
||||
|
||||
local pts = advtrains.encode_pos
|
||||
local stp = advtrains.decode_pos
|
||||
|
||||
--- Replace the distant signal assignment database.
|
||||
-- @function load
|
||||
-- @param db The new database to load.
|
||||
local function db_load(x)
|
||||
if type(x) ~= "table" then
|
||||
return
|
||||
end
|
||||
db_distant = x.distant
|
||||
db_distant_of = x.distant_of
|
||||
end
|
||||
|
||||
--- Retrieve the current distant signal assignment database.
|
||||
-- @function save
|
||||
-- @return The current database.
|
||||
local function db_save()
|
||||
return {
|
||||
distant = db_distant,
|
||||
distant_of = db_distant_of,
|
||||
}
|
||||
end
|
||||
|
||||
local update_signal, update_main, update_dst
|
||||
|
||||
--- Unassign a distant signal.
|
||||
-- @function unassign_dst
|
||||
-- @param dst The position of the distant signal.
|
||||
-- @param[opt=false] force Whether to skip callbacks.
|
||||
local function unassign_dst(dst, force)
|
||||
local pts_dst = pts(dst)
|
||||
local main = db_distant_of[pts_dst]
|
||||
db_distant_of[pts_dst] = nil
|
||||
if main then
|
||||
local pts_main = main[1]
|
||||
local t = db_distant[pts_main]
|
||||
if t then
|
||||
t[pts_dst] = nil
|
||||
end
|
||||
end
|
||||
if not force then
|
||||
update_dst(dst)
|
||||
end
|
||||
end
|
||||
|
||||
--- Unassign a main signal.
|
||||
-- @function unassign_main
|
||||
-- @param main The position of the main signal.
|
||||
-- @param[opt=false] force Whether to skip callbacks.
|
||||
local function unassign_main(main, force)
|
||||
local pts_main = pts(main)
|
||||
local t = db_distant[pts_main]
|
||||
if not t then
|
||||
return
|
||||
end
|
||||
for pts_dst in pairs(t) do
|
||||
local realmain = db_distant_of[pts_dst]
|
||||
if realmain and realmain[1] == pts_main then
|
||||
db_distant_of[pts_dst] = nil
|
||||
if not force then
|
||||
local dst = stp(pts_dst)
|
||||
update_dst(dst)
|
||||
end
|
||||
end
|
||||
end
|
||||
db_distant[pts_main] = nil
|
||||
end
|
||||
|
||||
--- Remove all (main and distant) signal assignments from a signal.
|
||||
-- @function unassign_all
|
||||
-- @param pos The position of the signal.
|
||||
-- @param[opt=false] force Whether to skip callbacks.
|
||||
local function unassign_all(pos, force)
|
||||
unassign_main(pos)
|
||||
unassign_dst(pos, force)
|
||||
end
|
||||
|
||||
--- Check whether a signal is "appropriate" for the distant signal system.
|
||||
-- Currently, a signal is considered appropriate if its signal aspect can be set.
|
||||
-- @function appropriate_signal
|
||||
-- @param pos The position of the signal
|
||||
local function appropriate_signal(pos)
|
||||
local node = advtrains.ndb.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name] or {}
|
||||
if not ndef then
|
||||
return false
|
||||
end
|
||||
local atdef = ndef.advtrains
|
||||
if not atdef then
|
||||
return false
|
||||
end
|
||||
return atdef.supported_aspects and atdef.set_aspect and true
|
||||
end
|
||||
|
||||
--- Assign a distant signal to a main signal.
|
||||
-- @function assign
|
||||
-- @param main The position of the main signal.
|
||||
-- @param dst The position of the distant signal.
|
||||
-- @param[opt="manual"] by The method of assignment.
|
||||
-- @param[opt=false] skip_update Whether to skip callbacks.
|
||||
local function assign(main, dst, by, skip_update)
|
||||
if not (appropriate_signal(main) and appropriate_signal(dst)) then
|
||||
return
|
||||
end
|
||||
local pts_main = pts(main)
|
||||
local pts_dst = pts(dst)
|
||||
local t = db_distant[pts_main]
|
||||
if not t then
|
||||
t = {}
|
||||
db_distant[pts_main] = t
|
||||
end
|
||||
if not by then
|
||||
by = "manual"
|
||||
end
|
||||
unassign_dst(dst, true)
|
||||
t[pts_dst] = by
|
||||
db_distant_of[pts_dst] = {pts_main, by}
|
||||
if not skip_update then
|
||||
update_dst(dst)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the distant signals assigned to a main signal.
|
||||
-- @function get_distant
|
||||
-- @param main The position of the main signal.
|
||||
-- @treturn {[pos]=by,...} A table of distant signals, with the positions encoded using `advtrains.encode_pos`.
|
||||
local function get_distant(main)
|
||||
local pts_main = pts(main)
|
||||
return db_distant[pts_main] or {}
|
||||
end
|
||||
|
||||
--- Get the main signal assigned the a distant signal.
|
||||
-- @function get_main
|
||||
-- @param dst The position of the distant signal.
|
||||
-- @return The position of the main signal.
|
||||
-- @return The method of assignment.
|
||||
local function get_main(dst)
|
||||
local pts_dst = pts(dst)
|
||||
local main = db_distant_of[pts_dst]
|
||||
if not main then
|
||||
return
|
||||
end
|
||||
if main[1] then
|
||||
return stp(main[1]), unpack(main, 2)
|
||||
else
|
||||
return unpack(main)
|
||||
end
|
||||
end
|
||||
|
||||
--- Update all distant signals assigned to a main signal.
|
||||
-- @function update_main
|
||||
-- @param main The position of the main signal.
|
||||
update_main = function(main)
|
||||
local pts_main = pts(main)
|
||||
local t = get_distant(main)
|
||||
for pts_dst in pairs(t) do
|
||||
local dst = stp(pts_dst)
|
||||
advtrains.interlocking.signal_readjust_aspect(dst)
|
||||
end
|
||||
end
|
||||
|
||||
--- Update the aspect of a distant signal.
|
||||
-- @function update_dst
|
||||
-- @param dst The position of the distant signal.
|
||||
update_dst = function(dst)
|
||||
advtrains.interlocking.signal_readjust_aspect(dst)
|
||||
end
|
||||
|
||||
--- Update the aspect of a combined (main and distant) signal and all distant signals assigned to it.
|
||||
-- @function update_signal
|
||||
-- @param pos The position of the signal.
|
||||
update_signal = function(pos)
|
||||
update_main(pos)
|
||||
update_dst(pos)
|
||||
end
|
||||
|
||||
advtrains.distant = {
|
||||
load = db_load,
|
||||
save = db_save,
|
||||
assign = assign,
|
||||
unassign_dst = unassign_dst,
|
||||
unassign_main = unassign_main,
|
||||
unassign_all = unassign_all,
|
||||
get_distant = get_distant,
|
||||
get_dst = get_distant,
|
||||
get_main = get_main,
|
||||
update_main = update_main,
|
||||
update_dst = update_dst,
|
||||
update_signal = update_signal,
|
||||
appropriate_signal = appropriate_signal,
|
||||
}
|
|
@ -15,9 +15,6 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELI
|
|||
--advtrains.interlocking.aspect = dofile(modpath.."aspect.lua")
|
||||
|
||||
dofile(modpath.."database.lua")
|
||||
dofile(modpath.."distant.lua")
|
||||
dofile(modpath.."distant_ui.lua")
|
||||
dofile(modpath.."signal_aspect_accessors.lua")
|
||||
dofile(modpath.."signal_api.lua")
|
||||
dofile(modpath.."signal_aspect_ui.lua")
|
||||
dofile(modpath.."demosignals.lua")
|
||||
|
|
|
@ -33,7 +33,7 @@ function atil.show_route_edit_form(pname, sigd, routeid)
|
|||
local function itab(t)
|
||||
tab[#tab+1] = minetest.formspec_escape(string.gsub(t, ",", " "))
|
||||
end
|
||||
itab("TCB "..sigd_to_string(sigd).." ("..(tcbs.signal_name or "")..") Route #"..routeid)
|
||||
itab("("..(tcbs.signal_name or "+")..") Route #"..routeid)
|
||||
|
||||
-- this code is partially copy-pasted from routesetting.lua
|
||||
-- we start at the tc designated by signal
|
||||
|
@ -56,13 +56,14 @@ function atil.show_route_edit_form(pname, sigd, routeid)
|
|||
c_rseg = route[i]
|
||||
c_lckp = {}
|
||||
|
||||
itab(""..i.." Entry "..sigd_to_string(c_sigd).." -> Sec. "..(c_ts and c_ts.name or "-").." -> Exit "..(c_rseg.next and sigd_to_string(c_rseg.next) or "END"))
|
||||
itab(""..i.." "..sigd_to_string(c_sigd))
|
||||
itab("= "..(c_ts and c_ts.name or "-").." =")
|
||||
|
||||
if c_rseg.locks then
|
||||
for pts, state in pairs(c_rseg.locks) do
|
||||
|
||||
local pos = minetest.string_to_pos(pts)
|
||||
itab(" Lock: "..pts.." -> "..state)
|
||||
itab("L "..pts.." -> "..state)
|
||||
if not advtrains.is_passive(pos) then
|
||||
itab("-!- No passive component at "..pts..". Please reconfigure route!")
|
||||
break
|
||||
|
@ -75,16 +76,17 @@ function atil.show_route_edit_form(pname, sigd, routeid)
|
|||
end
|
||||
if c_sigd then
|
||||
local e_tcbs = ildb.get_tcbs(c_sigd)
|
||||
itab("Route end: "..sigd_to_string(c_sigd).." ("..(e_tcbs and e_tcbs.signal_name or "-")..")")
|
||||
local signame = "-"
|
||||
if e_tcbs and e_tcbs.signal then signame = e_tcbs.signal_name or "+" end
|
||||
itab("E "..sigd_to_string(c_sigd).." ("..signame..")")
|
||||
else
|
||||
itab("Route ends on dead-end")
|
||||
itab("E (none)")
|
||||
end
|
||||
|
||||
form = form.."textlist[0.5,2;7.75,3.9;rtelog;"..table.concat(tab, ",").."]"
|
||||
form = form.."textlist[0.5,2;3,3.9;rtelog;"..table.concat(tab, ",").."]"
|
||||
|
||||
form = form.."button[0.5,6;3,1;back;<<< Back to signal]"
|
||||
form = form.."button[4.5,6;2,1;aspect;Signal Aspect]"
|
||||
form = form.."button[6.5,6;2,1;delete;Delete Route]"
|
||||
form = form.."button[5.5,6;3,1;delete;Delete Route]"
|
||||
|
||||
--atdebug(route.ars)
|
||||
form = form.."style[ars;font=mono]"
|
||||
|
|
|
@ -138,7 +138,7 @@ function ilrs.set_route(signal, route, try)
|
|||
}
|
||||
if c_tcbs.signal then
|
||||
c_tcbs.route_committed = true
|
||||
c_tcbs.aspect = route.aspect or advtrains.interlocking.FULL_FREE
|
||||
c_tcbs.aspect = advtrains.interlocking.signal.MASP_FREE
|
||||
c_tcbs.route_origin = signal
|
||||
signals[#signals+1] = c_tcbs
|
||||
end
|
||||
|
@ -166,7 +166,7 @@ function ilrs.set_route(signal, route, try)
|
|||
if (not nodst) and (not assigned_by or assigned_by == "routesetting") then
|
||||
advtrains.distant.assign(lastsig, pos, "routesetting", true)
|
||||
end
|
||||
advtrains.interlocking.update_signal_aspect(tcbs, i ~= 1)
|
||||
advtrains.interlocking.signal.update_route_aspect(tcbs, i ~= 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -278,14 +278,7 @@ function ilrs.cancel_route_from(sigd)
|
|||
c_tcbs.route_auto = nil
|
||||
c_tcbs.route_origin = nil
|
||||
|
||||
if c_tcbs.signal then
|
||||
local pos = c_tcbs.signal
|
||||
local _, assigned_by = advtrains.distant.get_main(pos)
|
||||
if assigned_by == "routesetting" then
|
||||
advtrains.distant.unassign_dst(pos, true)
|
||||
end
|
||||
end
|
||||
advtrains.interlocking.update_signal_aspect(c_tcbs)
|
||||
advtrains.interlocking.signal.update_route_aspect(c_tcbs)
|
||||
|
||||
c_ts_id = c_tcbs.ts_id
|
||||
if not c_tcbs then
|
||||
|
@ -370,7 +363,7 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
|
|||
end
|
||||
if has_changed_aspect then
|
||||
-- FIX: prevent an minetest.after() loop caused by update_signal_aspect dispatching path invalidation, which in turn calls ARS again
|
||||
advtrains.interlocking.update_signal_aspect(tcbs)
|
||||
advtrains.interlocking.signal.update_route_aspect(tcbs)
|
||||
end
|
||||
advtrains.interlocking.update_player_forms(sigd)
|
||||
end
|
||||
|
|
|
@ -5,9 +5,15 @@ local F = advtrains.formspec
|
|||
local signal = {}
|
||||
|
||||
signal.MASP_HALT = {
|
||||
name = "halt",
|
||||
description = "HALT",
|
||||
halt = true,
|
||||
name = nil,
|
||||
speed = nil,
|
||||
remote = nil,
|
||||
}
|
||||
|
||||
signal.MASP_FREE = {
|
||||
name = "_free",
|
||||
speed = -1,
|
||||
remote = nil,
|
||||
}
|
||||
|
||||
signal.ASPI_HALT = {
|
||||
|
@ -50,11 +56,12 @@ Note that once apply_aspect returns, there is no need for advtrains anymore to q
|
|||
When the signal, for any reason, wants to change its aspect by itself *without* going through the signal API then
|
||||
it should update the aspect info cache by calling advtrains.interlocking.signal.update_aspect_info(pos)
|
||||
|
||||
Note that the apply_aspect function MUST accept the following main aspect, even if it is not defined in the main_aspects table:
|
||||
{ name = "halt", halt = true }
|
||||
It should cause the signal to show its most restrictive aspect. Typically it is a halt aspect, but e.g. for distant-only
|
||||
Apply_aspect may also receive nil as the main aspect. It usually means that the signal is not assigned to anything particular,
|
||||
and it should cause the signal to show its most restrictive aspect. Typically it is a halt aspect, but e.g. for distant-only
|
||||
signals this would be "expect stop".
|
||||
|
||||
Main aspect names starting with underscore (e.g. "_default") are reserved and must not be used!
|
||||
|
||||
== Aspect Info ==
|
||||
The actual signal aspect in the already-known format. This is what the trains use to determine halt/proceed and speed.
|
||||
asp = {
|
||||
|
@ -152,7 +159,7 @@ end
|
|||
-- - Storing the main aspect and dst pos for this signal permanently (until next change)
|
||||
-- - Assigning the distant signal for this signal
|
||||
-- - Calling apply_aspect() in the signal's node definition to make the signal show the aspect
|
||||
-- - Calling apply_aspect() again whenever the distant signal changes its aspect
|
||||
-- - Calling apply_aspect() again whenever the remote signal changes its aspect
|
||||
-- - Notifying this signal's distant signals about changes to this signal (unless skip_dst_notify is specified)
|
||||
function signal.set_aspect(pos, main_asp_name, main_asp_speed, rem_pos, skip_dst_notify)
|
||||
local main_pts = advtrains.encode_pos(pos)
|
||||
|
@ -252,10 +259,7 @@ function signal.get_aspect(pos)
|
|||
end
|
||||
|
||||
local function cache_mainaspects(ndefat)
|
||||
ndefat.main_aspects_lookup = {
|
||||
-- always define halt aspect
|
||||
halt = signal.MASP_HALT
|
||||
}
|
||||
ndefat.main_aspects_lookup = {}
|
||||
for _,ma in ipairs(ndefat.main_aspects) do
|
||||
ndefat.main_aspects_lookup[ma.name] = ma
|
||||
end
|
||||
|
@ -264,7 +268,7 @@ end
|
|||
function signal.get_aspect_internal(pos, aspt)
|
||||
if not aspt then
|
||||
-- oh, no main aspect, nevermind
|
||||
return nil, aspt.remote, nil
|
||||
return nil, nil, nil
|
||||
end
|
||||
atdebug("get_aspect_internal",pos,aspt)
|
||||
-- look aspect in nodedef
|
||||
|
@ -277,6 +281,10 @@ function signal.get_aspect_internal(pos, aspt)
|
|||
cache_mainaspects(ndefat)
|
||||
end
|
||||
local masp = ndefat.main_aspects_lookup[aspt.name]
|
||||
-- special handling for the default free aspect ("_free")
|
||||
if aspt.name == "_free" then
|
||||
masp = ndefat.main_aspects[1]
|
||||
end
|
||||
if not masp then
|
||||
atwarn(pos,"invalid main aspect",aspt.name,"valid are",ndefat.main_aspects_lookup)
|
||||
return nil, aspt.remote, node, ndef
|
||||
|
@ -355,10 +363,30 @@ end
|
|||
function signal.update_route_aspect(tcbs, skip_dst_notify)
|
||||
if tcbs.signal then
|
||||
local asp = tcbs.aspect or signal.MASP_HALT
|
||||
signal.set_aspect(tcbs.signal, asp, skip_dst_notify)
|
||||
signal.set_aspect(tcbs.signal, asp.name, asp.speed, asp.remote, skip_dst_notify)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns how capable the signal is with regards to aspect setting
|
||||
-- 0: not a signal at all
|
||||
-- 1: signal has get_aspect_info() but the aspect is not variable (e.g. a sign)
|
||||
-- 2: signal has apply_aspect() but does not have main aspects (e.g. a pure distant signal)
|
||||
-- 3: Full capabilities, signal has main aspects and can be used as main/shunt signal (can be start/endpoint of a route)
|
||||
function signal.get_signal_cap_level(pos)
|
||||
local node = advtrains.ndb.get_node_or_nil(pos)
|
||||
local ndef = node and minetest.registered_nodes[node.name]
|
||||
local ndefat = ndef and ndef.advtrains
|
||||
if ndefat and ndefat.get_aspect_info then
|
||||
if ndefat.apply_aspect then
|
||||
if ndefat.main_aspects then
|
||||
return 3
|
||||
end
|
||||
return 2
|
||||
end
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
----------------
|
||||
|
||||
|
@ -366,7 +394,7 @@ function signal.can_dig(pos)
|
|||
return not advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||
end
|
||||
|
||||
function advtrains.interlocking.signal_after_dig(pos)
|
||||
function signal.after_dig(pos)
|
||||
-- TODO clear influence point
|
||||
advtrains.interlocking.signal.clear_aspect(pos)
|
||||
end
|
||||
|
@ -374,169 +402,7 @@ end
|
|||
function signal.on_rightclick(pos, node, player, itemstack, pointed_thing)
|
||||
local pname = player:get_player_name()
|
||||
local control = player:get_player_control()
|
||||
if control.aux1 then
|
||||
advtrains.interlocking.show_ip_form(pos, pname)
|
||||
return
|
||||
end
|
||||
advtrains.interlocking.show_signal_form(pos, node, pname)
|
||||
advtrains.interlocking.show_signal_form(pos, node, pname, control.aux1)
|
||||
end
|
||||
|
||||
function advtrains.interlocking.show_signal_form(pos, node, pname)
|
||||
local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||
if sigd then
|
||||
advtrains.interlocking.show_signalling_form(sigd, pname)
|
||||
else
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef.advtrains and ndef.advtrains.set_aspect then
|
||||
-- permit to set aspect manually
|
||||
local function callback(pname, aspect)
|
||||
signal.set_aspect(pos, aspect)
|
||||
end
|
||||
local isasp = advtrains.interlocking.signal_get_aspect(pos, node)
|
||||
|
||||
advtrains.interlocking.show_signal_aspect_selector(
|
||||
pname,
|
||||
ndef.advtrains.supported_aspects,
|
||||
pos, callback,
|
||||
isasp)
|
||||
else
|
||||
--static signal - only IP
|
||||
advtrains.interlocking.show_ip_form(pos, pname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local players_assign_ip = {}
|
||||
|
||||
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
|
||||
|
||||
function advtrains.interlocking.make_ip_formspec_component(pos, x, y, w)
|
||||
advtrains.interlocking.db.check_for_duplicate_ip(pos)
|
||||
local pts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos)
|
||||
if pts then
|
||||
return table.concat {
|
||||
F.S_label(x, y, "Influence point is set at @1.", string.format("%s/%s", pts, connid)),
|
||||
F.S_button_exit(x, y+0.5, w/2-0.125, "ip_set", "Modify"),
|
||||
F.S_button_exit(x+w/2+0.125, y+0.5, w/2-0.125, "ip_clear", "Clear"),
|
||||
}, pts, connid
|
||||
else
|
||||
return table.concat {
|
||||
F.S_label(x, y, "Influence point is not set."),
|
||||
F.S_button_exit(x, y+0.5, w, "ip_set", "Set influence point"),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- shows small info form for signal properties
|
||||
-- This function is named show_ip_form because it was originally only intended
|
||||
-- for assigning/changing the influence point.
|
||||
-- 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)
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
return
|
||||
end
|
||||
local ipform, pts, connid = advtrains.interlocking.make_ip_formspec_component(pos, 0.5, 0.5, 7)
|
||||
local form = {
|
||||
"formspec_version[4]",
|
||||
"size[8,2.25]",
|
||||
ipform,
|
||||
}
|
||||
if pts then
|
||||
local ipos = minetest.string_to_pos(pts)
|
||||
ipmarker(ipos, connid)
|
||||
end
|
||||
if advtrains.distant.appropriate_signal(pos) then
|
||||
form[#form+1] = advtrains.interlocking.make_dst_formspec_component(pos, 0.5, 2, 7, 4.25)
|
||||
form[2] = "size[8,6.75]"
|
||||
end
|
||||
form = table.concat(form)
|
||||
if not only_notset or not pts then
|
||||
minetest.show_formspec(pname, "at_il_propassign_"..minetest.pos_to_string(pos), form)
|
||||
end
|
||||
end
|
||||
|
||||
function advtrains.interlocking.handle_ip_formspec_fields(pname, pos, fields)
|
||||
if not (pos and minetest.check_player_privs(pname, {train_operator=true, interlocking=true})) then
|
||||
return
|
||||
end
|
||||
if fields.ip_set then
|
||||
advtrains.interlocking.signal_init_ip_assign(pos, pname)
|
||||
elseif fields.ip_clear then
|
||||
advtrains.interlocking.db.clear_ip_by_signalpos(pos)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
local pts = string.match(formname, "^at_il_propassign_([^_]+)$")
|
||||
local pos
|
||||
if pts then
|
||||
pos = minetest.string_to_pos(pts)
|
||||
end
|
||||
if pos then
|
||||
advtrains.interlocking.handle_ip_formspec_fields(pname, pos, fields)
|
||||
advtrains.interlocking.handle_dst_formspec_fields(pname, pos, fields)
|
||||
end
|
||||
end)
|
||||
|
||||
-- inits the signal IP assignment process
|
||||
function 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)
|
||||
|
||||
|
||||
advtrains.interlocking.signal = signal
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
--- Signal aspect accessors
|
||||
-- @module advtrains.interlocking
|
||||
|
||||
local A = advtrains.interlocking.aspect
|
||||
local D = advtrains.distant
|
||||
local I = advtrains.interlocking
|
||||
local N = advtrains.ndb
|
||||
local pts = advtrains.roundfloorpts
|
||||
|
||||
local get_aspect
|
||||
|
||||
local supposed_aspects = {}
|
||||
|
||||
--- Replace the signal aspect cache.
|
||||
-- @function load_supposed_aspects
|
||||
-- @param db The new database.
|
||||
function I.load_supposed_aspects(tbl)
|
||||
if tbl then
|
||||
supposed_aspects = {}
|
||||
for k, v in pairs(tbl) do
|
||||
supposed_aspects[k] = A(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Retrieve the signal aspect cache.
|
||||
-- @function save_supposed_aspects
|
||||
-- @return The current database in use.
|
||||
function I.save_supposed_aspects()
|
||||
local t = {}
|
||||
for k, v in pairs(supposed_aspects) do
|
||||
t[k] = v:plain(true)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--- Read the aspect of a signal strictly from cache.
|
||||
-- @param pos The position of the signal.
|
||||
-- @return[1] The aspect of the signal (if present in cache).
|
||||
-- @return[2] The nil constant (otherwise).
|
||||
local function get_supposed_aspect(pos)
|
||||
return supposed_aspects[pts(pos)]
|
||||
end
|
||||
|
||||
--- Update the signal aspect information in cache.
|
||||
-- @param pos The position of the signal.
|
||||
-- @param asp The new signal aspect
|
||||
local function set_supposed_aspect(pos, asp)
|
||||
supposed_aspects[pts(pos)] = asp
|
||||
end
|
||||
|
||||
--- Get the definition of a node.
|
||||
-- @param pos The position of the node.
|
||||
-- @return[1] The definition of the node (if present).
|
||||
-- @return[2] An empty table (otherwise).
|
||||
local function get_ndef(pos)
|
||||
local node = N.get_node(pos)
|
||||
return (minetest.registered_nodes[node.name] or {}), node
|
||||
end
|
||||
|
||||
--- Get the aspects supported by a signal.
|
||||
-- @function signal_get_supported_aspects
|
||||
-- @param pos The position of the signal.
|
||||
-- @return[1] The table of supported aspects (if present).
|
||||
-- @return[2] The nil constant (otherwise).
|
||||
local function get_supported_aspects(pos)
|
||||
local ndef = get_ndef(pos)
|
||||
if ndef.advtrains and ndef.advtrains.supported_aspects then
|
||||
return ndef.advtrains.supported_aspects
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Adjust a new signal aspect to fit a signal.
|
||||
-- @param pos The position of the signal.
|
||||
-- @param asp The new signal aspect.
|
||||
-- @return The adjusted signal aspect.
|
||||
-- @return The information to pass to the `advtrains.set_aspect` field in the node definitions.
|
||||
local function adjust_aspect(pos, asp)
|
||||
local asp = A(asp)
|
||||
|
||||
local mainpos = D.get_main(pos)
|
||||
local nxtasp
|
||||
if mainpos then
|
||||
nxtasp = get_aspect(mainpos)
|
||||
end
|
||||
local suppasp = get_supported_aspects(pos)
|
||||
if not suppasp then
|
||||
return asp
|
||||
end
|
||||
return asp:adjust_distant(nxtasp, suppasp.dst_shift):to_group(suppasp.group)
|
||||
end
|
||||
|
||||
--- Get the aspect of a signal without accessing the cache.
|
||||
-- For most cases, `get_aspect` should be used instead.
|
||||
-- @function signal_get_real_aspect
|
||||
-- @param pos The position of the signal.
|
||||
-- @return[1] The signal aspect adjusted using `adjust_aspect` (if present).
|
||||
-- @return[2] The nil constant (otherwise).
|
||||
local function get_real_aspect(pos)
|
||||
local ndef, node = get_ndef(pos)
|
||||
if ndef.advtrains and ndef.advtrains.get_aspect then
|
||||
local asp = ndef.advtrains.get_aspect(pos, node) or I.DANGER
|
||||
return adjust_aspect(pos, asp)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the aspect of a signal.
|
||||
-- @function signal_get_aspect
|
||||
-- @param pos The position of the signal.
|
||||
-- @return[1] The aspect of the signal (if present).
|
||||
-- @return[2] The nil constant (otherwise).
|
||||
get_aspect = function(pos)
|
||||
local asp = get_supposed_aspect(pos)
|
||||
if not asp then
|
||||
asp = get_real_aspect(pos)
|
||||
set_supposed_aspect(pos, asp)
|
||||
end
|
||||
return asp
|
||||
end
|
||||
|
||||
--- Set the aspect of a signal.
|
||||
-- @function signal_set_aspect
|
||||
-- @param pos The position of the signal.
|
||||
-- @param asp The new signal aspect.
|
||||
-- @param[opt=false] skipdst Whether to skip updating distant signals.
|
||||
local function set_aspect(pos, asp, skipdst)
|
||||
local node = N.get_node(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.advtrains and ndef.advtrains.set_aspect then
|
||||
local oldasp = I.signal_get_aspect(pos) or DANGER
|
||||
local newasp = adjust_aspect(pos, asp)
|
||||
set_supposed_aspect(pos, newasp)
|
||||
ndef.advtrains.set_aspect(pos, node, newasp)
|
||||
I.signal_on_aspect_changed(pos)
|
||||
local aspect_changed = oldasp ~= newasp
|
||||
if (not skipdst) and aspect_changed then
|
||||
D.update_main(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove a signal from cache.
|
||||
-- @function signal_clear_aspect
|
||||
-- @param pos The position of the signal.
|
||||
local function clear_aspect(pos)
|
||||
set_supposed_aspect(pos, nil)
|
||||
end
|
||||
|
||||
--- Readjust the aspect of a signal.
|
||||
-- @function signal_readjust_aspect
|
||||
-- @param pos The position of the signal.
|
||||
local function readjust_aspect(pos)
|
||||
set_aspect(pos, get_aspect(pos))
|
||||
end
|
||||
|
||||
I.signal_get_supported_aspects = get_supported_aspects
|
||||
I.signal_get_real_aspect = get_real_aspect
|
||||
I.signal_get_aspect = get_aspect
|
||||
I.signal_set_aspect = set_aspect
|
||||
I.signal_clear_aspect = clear_aspect
|
||||
I.signal_readjust_aspect = readjust_aspect
|
|
@ -1,262 +1,188 @@
|
|||
local F = advtrains.formspec
|
||||
local players_aspsel = {}
|
||||
|
||||
local function describe_main_aspect(spv)
|
||||
if spv == 0 then
|
||||
return attrans("Danger (halt)")
|
||||
elseif spv == -1 then
|
||||
return attrans("Continue at maximum speed")
|
||||
elseif not spv then
|
||||
return attrans("Continue with current speed limit")
|
||||
function advtrains.interlocking.show_signal_form(pos, node, pname, aux_key)
|
||||
local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||
if sigd and not aux_key then
|
||||
advtrains.interlocking.show_signalling_form(sigd, pname)
|
||||
else
|
||||
return attrans("Continue with the speed limit of @1", tostring(spv))
|
||||
if advtrains.interlocking.signal.get_signal_cap_level(pos) >= 2 then
|
||||
advtrains.interlocking.show_ip_sa_form(pos, pname)
|
||||
else
|
||||
advtrains.interlocking.show_ip_form(pos, pname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function describe_shunt_aspect(shunt)
|
||||
if shunt then
|
||||
return attrans("Shunting allowed")
|
||||
else
|
||||
return attrans("No shunting")
|
||||
end
|
||||
local players_assign_ip = {}
|
||||
local players_assign_distant = {}
|
||||
|
||||
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
|
||||
|
||||
local function describe_distant_aspect(spv)
|
||||
if spv == 0 then
|
||||
return attrans("Expect to stop at the next signal")
|
||||
elseif spv == -1 then
|
||||
return attrans("Expect to continue at maximum speed")
|
||||
elseif not spv then
|
||||
return attrans("No distant signal information")
|
||||
else
|
||||
return attrans("Expect to continue with a speed limit of @1", tostring(spv))
|
||||
end
|
||||
end
|
||||
|
||||
advtrains.interlocking.describe_main_aspect = describe_main_aspect
|
||||
advtrains.interlocking.describe_shunt_aspect = describe_shunt_aspect
|
||||
advtrains.interlocking.describe_distant_aspect = describe_distant_aspect
|
||||
|
||||
local function dsel(p, q, x, y)
|
||||
if p == nil then
|
||||
if q then
|
||||
return x
|
||||
else
|
||||
return y
|
||||
end
|
||||
elseif p then
|
||||
return x
|
||||
else
|
||||
return y
|
||||
end
|
||||
end
|
||||
|
||||
local function describe_supported_aspects(suppasp, isasp)
|
||||
local t = {}
|
||||
|
||||
local entries = {attrans("Use default value")}
|
||||
local selid = 0
|
||||
local mainasps = suppasp.main
|
||||
if type(mainasps) ~= "table" then
|
||||
mainasps = {mainasps}
|
||||
end
|
||||
for idx, spv in ipairs(mainasps) do
|
||||
if isasp and spv == rawget(isasp, "main") then
|
||||
selid = idx
|
||||
end
|
||||
entries[idx+1] = describe_main_aspect(spv)
|
||||
end
|
||||
t.main = entries
|
||||
t.main_current = selid+1
|
||||
t.main_string = tostring(isasp.main)
|
||||
if t.main == nil then
|
||||
t.main_string = ""
|
||||
end
|
||||
|
||||
t.shunt = {
|
||||
attrans("No shunting"),
|
||||
attrans("Shunting allowed"),
|
||||
attrans("Proceed as main"),
|
||||
function advtrains.interlocking.make_ip_formspec_component(pos, x, y, w)
|
||||
advtrains.interlocking.db.check_for_duplicate_ip(pos)
|
||||
local pts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos)
|
||||
if pts then
|
||||
-- display marker
|
||||
local ipos = minetest.string_to_pos(pts)
|
||||
ipmarker(ipos, connid)
|
||||
return table.concat {
|
||||
F.S_label(x, y, "Influence point is set at @1.", string.format("%s/%s", pts, connid)),
|
||||
F.S_button_exit(x, y+0.5, w/2-0.125, "ip_set", "Modify"),
|
||||
F.S_button_exit(x+w/2+0.125, y+0.5, w/2-0.125, "ip_clear", "Clear"),
|
||||
}
|
||||
else
|
||||
return table.concat {
|
||||
F.S_label(x, y, "Influence point is not set."),
|
||||
F.S_button_exit(x, y+0.5, w, "ip_set", "Set influence point"),
|
||||
}
|
||||
|
||||
t.shunt_current = dsel(suppasp.shunt, isasp.shunt, 2, 1)
|
||||
if dsel(suppasp.proceed_as_main, isasp.proceed_as_main, t.shunt_current == 1) then
|
||||
t.shunt_current = 3
|
||||
end
|
||||
t.shunt_const = suppasp.shunt ~= nil
|
||||
|
||||
if suppasp.group then
|
||||
local gdef = advtrains.interlocking.aspect.get_group_definition(suppasp.group)
|
||||
if gdef then
|
||||
t.group = suppasp.group
|
||||
t.groupdef = gdef
|
||||
local entries = {}
|
||||
local selid = 1
|
||||
for idx, name in ipairs(suppasp.name or {}) do
|
||||
entries[idx] = gdef.aspects[name].label
|
||||
if suppasp.group == isasp.group and name == isasp.name then
|
||||
selid = idx
|
||||
end
|
||||
end
|
||||
t.name = entries
|
||||
t.name_current = selid
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
advtrains.interlocking.describe_supported_aspects = describe_supported_aspects
|
||||
|
||||
local function make_signal_aspect_selector(suppasp, purpose, isasp)
|
||||
local t = describe_supported_aspects(suppasp, isasp)
|
||||
local formmode = 1
|
||||
|
||||
local pos
|
||||
if type(purpose) == "table" then
|
||||
formmode = 2
|
||||
pos = purpose.pos
|
||||
end
|
||||
|
||||
local form = {
|
||||
"formspec_version[4]",
|
||||
string.format("size[8,%f]", ({5.75, 10.75})[formmode]),
|
||||
F.S_label(0.5, 0.5, "Select signal aspect"),
|
||||
}
|
||||
local h0 = ({0, 1.5})[formmode]
|
||||
form[#form+1] = F.S_label(0.5, 1.5+h0, "Main aspect")
|
||||
form[#form+1] = F.S_label(0.5, 3+h0, "Shunt aspect")
|
||||
form[#form+1] = F.S_button_exit(0.5, 4.5+h0, 7, "asp_save", "Save signal aspect")
|
||||
if formmode == 1 then
|
||||
form[#form+1] = F.label(0.5, 1, purpose)
|
||||
form[#form+1] = F.field(0.5, 2, 7, "asp_mainval", "", t.main_string)
|
||||
elseif formmode == 2 then
|
||||
if t.group then
|
||||
form[#form+1] = F.S_label(0.5, 1.5, "Signal aspect group: @1", t.groupdef.label)
|
||||
form[#form+1] = F.dropdown(0.5, 2, 7, "asp_namesel", t.name, t.name_current, true)
|
||||
else
|
||||
form[#form+1] = F.S_label(0.5, 1.5, "This signal does not belong to a signal aspect group.")
|
||||
form[#form+1] = F.S_label(0.5, 2, "You can not use a predefined signal aspect.")
|
||||
end
|
||||
form[#form+1] = F.S_label(0.5, 1, "Signal at @1", minetest.pos_to_string(pos))
|
||||
form[#form+1] = F.dropdown(0.5, 3.5, 7, "asp_mainsel", t.main, t.main_current, true)
|
||||
form[#form+1] = advtrains.interlocking.make_ip_formspec_component(pos, 0.5, 7, 7)
|
||||
form[#form+1] = advtrains.interlocking.make_short_dst_formspec_component(pos, 0.5, 8.5, 7)
|
||||
end
|
||||
|
||||
if formmode == 2 and t.shunt_const then
|
||||
form[#form+1] = F.label(0.5, 3.5+h0, t.shunt[t.shunt_current])
|
||||
form[#form+1] = F.S_label(0.5, 4+h0, "The shunt aspect cannot be changed.")
|
||||
else
|
||||
form[#form+1] = F.dropdown(0.5, 3.5+h0, 7, "asp_shunt", t.shunt, t.shunt_current, true)
|
||||
end
|
||||
|
||||
return table.concat(form)
|
||||
end
|
||||
|
||||
function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_purpose, callback, isasp)
|
||||
local suppasp = p_suppasp or {
|
||||
main = {0, -1},
|
||||
dst = {false},
|
||||
shunt = false,
|
||||
info = {},
|
||||
}
|
||||
local purpose = p_purpose or ""
|
||||
local pos
|
||||
if type(p_purpose) == "table" then
|
||||
pos = p_purpose
|
||||
purpose = {pname = pname, pos = pos}
|
||||
end
|
||||
|
||||
local form = make_signal_aspect_selector(suppasp, purpose, isasp)
|
||||
if not form then
|
||||
-- shows small formspec to set the signal influence point
|
||||
-- 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)
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
return
|
||||
end
|
||||
|
||||
local token = advtrains.random_id()
|
||||
minetest.show_formspec(pname, "at_il_sigaspdia_"..token, form)
|
||||
minetest.after(0, function()
|
||||
players_aspsel[pname] = {
|
||||
purpose = purpose,
|
||||
suppasp = suppasp,
|
||||
callback = callback,
|
||||
token = token,
|
||||
local ipform = advtrains.interlocking.make_ip_formspec_component(pos, 0.5, 0.5, 7)
|
||||
local form = {
|
||||
"formspec_version[4]",
|
||||
"size[8,2.25]",
|
||||
ipform,
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
local function usebool(sup, val, free)
|
||||
if sup == nil then
|
||||
return val == free
|
||||
else
|
||||
return sup
|
||||
if not only_notset or not pts then
|
||||
minetest.show_formspec(pname, "at_il_ipsaform_"..minetest.pos_to_string(pos), table.concat(form))
|
||||
end
|
||||
end
|
||||
|
||||
local function get_aspect_from_formspec(suppasp, fields, psl)
|
||||
local namei, group, name = tonumber(fields.asp_namesel), suppasp.group, nil
|
||||
local gdef = advtrains.interlocking.aspect.get_group_definition(group)
|
||||
if gdef then
|
||||
local names = suppasp.name or {}
|
||||
name = names[namei] or names[names]
|
||||
else
|
||||
group = nil
|
||||
-- shows larger formspec to set the signal influence point, main aspect and distant signal pos
|
||||
-- only_notset: show only if it is not set yet (used by signal tcb assignment)
|
||||
function advtrains.interlocking.show_ip_sa_form(pos, pname)
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
return
|
||||
end
|
||||
local maini = tonumber(fields.asp_mainsel)
|
||||
local main = (suppasp.main or {})[(maini or 0)-1]
|
||||
if not maini then
|
||||
local mainval = fields.asp_mainval
|
||||
if mainval == "-1" then
|
||||
main = -1
|
||||
elseif mainval == "x" then
|
||||
main = false
|
||||
elseif string.match(mainval, "^%d+$") then
|
||||
main = tonumber(mainval)
|
||||
else
|
||||
main = nil
|
||||
end
|
||||
elseif maini <= 1 then
|
||||
main = nil
|
||||
end
|
||||
local shunti = tonumber(fields.asp_shunt)
|
||||
local shunt = suppasp.shunt
|
||||
if shunt == nil then
|
||||
shunt = shunti == 2
|
||||
end
|
||||
local proceed_as_main = suppasp.proceed_as_main
|
||||
if proceed_as_main == nil then
|
||||
proceed_as_main = shunti == 3
|
||||
end
|
||||
return advtrains.interlocking.aspect {
|
||||
main = main,
|
||||
shunt = shunt,
|
||||
proceed_as_main = proceed_as_main,
|
||||
info = {},
|
||||
name = name,
|
||||
group = group,
|
||||
local ipform = advtrains.interlocking.make_ip_formspec_component(pos, 0.5, 0.5, 7)
|
||||
local ma, rpos = advtrains.interlocking.signal.get_aspect(pos)
|
||||
local saform = F.S_button_exit(0, 2, 4, "sa_dst_assign", rpos and minetest.pos_to_string(rpos) or "<distant signal>")
|
||||
.. F.S_button_exit(0, 3, 2, "sa_tmp_mainfree", "Main to free") .. F.S_button_exit(2, 3, 2, "sa_tmp_mainhalt", "Main to halt")
|
||||
local form = {
|
||||
"formspec_version[4]",
|
||||
"size[8,4]",
|
||||
ipform,
|
||||
saform,
|
||||
}
|
||||
minetest.show_formspec(pname, "at_il_ipsaform_"..minetest.pos_to_string(pos), table.concat(form))
|
||||
end
|
||||
|
||||
function advtrains.interlocking.handle_ip_sa_formspec_fields(pname, pos, fields)
|
||||
if not (pos and minetest.check_player_privs(pname, {train_operator=true, interlocking=true})) then
|
||||
return
|
||||
end
|
||||
if fields.ip_set then
|
||||
advtrains.interlocking.init_ip_assign(pos, pname)
|
||||
elseif fields.ip_clear then
|
||||
advtrains.interlocking.db.clear_ip_by_signalpos(pos)
|
||||
elseif fields.sa_dst_assign then
|
||||
advtrains.interlocking.init_distant_assign(pos, pname)
|
||||
elseif fields.sa_tmp_mainfree then
|
||||
local ma, rpos = advtrains.interlocking.signal.get_aspect(pos)
|
||||
advtrains.interlocking.signal.set_aspect(pos, "_free", -1, rpos)
|
||||
elseif fields.sa_tmp_mainhalt then
|
||||
local ma, rpos = advtrains.interlocking.signal.get_aspect(pos)
|
||||
advtrains.interlocking.signal.set_aspect(pos, nil, nil, rpos)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local pname = player:get_player_name()
|
||||
local psl = players_aspsel[pname]
|
||||
if psl then
|
||||
if formname == "at_il_sigaspdia_"..psl.token then
|
||||
local suppasp = psl.suppasp
|
||||
if fields.asp_save then
|
||||
local asp
|
||||
asp = get_aspect_from_formspec(suppasp, fields, psl)
|
||||
if asp then
|
||||
psl.callback(pname, asp)
|
||||
end
|
||||
end
|
||||
if type(psl.purpose) == "table" then
|
||||
local pos = psl.purpose.pos
|
||||
advtrains.interlocking.handle_ip_formspec_fields(pname, pos, fields)
|
||||
advtrains.interlocking.handle_dst_formspec_fields(pname, pos, fields)
|
||||
end
|
||||
else
|
||||
players_aspsel[pname] = nil
|
||||
local pts = string.match(formname, "^at_il_ipsaform_([^_]+)$")
|
||||
local pos
|
||||
if pts then
|
||||
pos = minetest.string_to_pos(pts)
|
||||
end
|
||||
if pos then
|
||||
advtrains.interlocking.handle_ip_sa_formspec_fields(pname, pos, fields)
|
||||
end
|
||||
end)
|
||||
|
||||
-- inits the signal IP assignment process
|
||||
function advtrains.interlocking.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
|
||||
|
||||
-- inits the distant signal assignment process
|
||||
function advtrains.interlocking.init_distant_assign(pos, pname)
|
||||
if not minetest.check_player_privs(pname, "interlocking") then
|
||||
minetest.chat_send_player(pname, "Insufficient privileges to use this!")
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(pname, "Set distant signal: Punch the main signal to assign!")
|
||||
|
||||
players_assign_distant[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
|
||||
-- DST assignment
|
||||
signalpos = players_assign_distant[pname]
|
||||
if signalpos then
|
||||
-- get current mainaspect
|
||||
local ma, rpos = advtrains.interlocking.signal.get_aspect(signalpos)
|
||||
-- if punched pos is valid signal then set it as the new remote, otherwise nil
|
||||
local nrpos
|
||||
if advtrains.interlocking.signal.get_signal_cap_level(pos) > 1 then nrpos = pos end
|
||||
advtrains.interlocking.signal.set_aspect(signalpos, ma.name, ma.speed, nrpos)
|
||||
players_assign_distant[pname] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ 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
|
||||
|
@ -464,7 +464,7 @@ 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.."!")
|
||||
end
|
||||
|
@ -642,7 +642,6 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle
|
|||
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..string.format("checkbox[0.5,8.75;ars;Automatic routesetting;%s]", not tcbs.ars_disabled)
|
||||
form = form..string.format("checkbox[0.5,9.25;dst;Distant signalling;%s]", not tcbs.nodst)
|
||||
end
|
||||
elseif sigd_equal(tcbs.route_origin, sigd) then
|
||||
-- something has gone wrong: tcbs.routeset should have been set...
|
||||
|
@ -660,7 +659,7 @@ 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
|
||||
|
||||
|
@ -770,10 +769,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
tcbs.ars_disabled = not minetest.is_yes(fields.ars)
|
||||
end
|
||||
|
||||
if fields.dst then
|
||||
tcbs.nodst = not minetest.is_yes(fields.dst)
|
||||
end
|
||||
|
||||
if fields.auto then
|
||||
tcbs.route_auto = true
|
||||
end
|
||||
|
|
|
@ -374,10 +374,6 @@ for sigtype, sigdata in pairs {
|
|||
--sigdefs["rpt_"..sigtype] = process_signal(sigtype, sigdata, true)
|
||||
end
|
||||
|
||||
for k in pairs(sigdefs) do
|
||||
advtrains.trackplacer.register_tracktype("advtrains_signals_japan:"..k)
|
||||
end
|
||||
|
||||
for _, rtab in ipairs {
|
||||
{rot = "0", ici = true},
|
||||
{rot = "30"},
|
||||
|
@ -455,7 +451,7 @@ for _, rtab in ipairs {
|
|||
can_dig = advtrains.interlocking.signal_can_dig,
|
||||
after_dig_node = advtrains.interlocking.signal_after_dig,
|
||||
})
|
||||
advtrains.trackplacer.add_worked("advtrains_signals_japan:"..sigtype, asp, "_"..rot)
|
||||
--advtrains.trackplacer.add_worked("advtrains_signals_japan:"..sigtype, asp, "_"..rot)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,15 +50,18 @@ end
|
|||
|
||||
local applyaspectf_main = function(rot)
|
||||
return function(pos, node, main_aspect, dst_aspect, dst_aspect_info)
|
||||
if not main_aspect then
|
||||
-- halt aspect, set red and don't do anything further
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_danger_"..rot, param2 = node.param2})
|
||||
setzs3v(pos, nil, rot)
|
||||
return
|
||||
end
|
||||
-- set zs3 signal to show speed according to main_aspect
|
||||
setzs3(pos, main_aspect.zs3, rot)
|
||||
-- select appropriate lamps based on mainaspect and dst
|
||||
if main_aspect.shunt then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_shunt_"..rot, param2 = node.param2})
|
||||
setzs3v(pos, nil, rot)
|
||||
elseif main_aspect.halt then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_danger_"..rot, param2 = node.param2})
|
||||
setzs3v(pos, nil, rot)
|
||||
else
|
||||
if not dst_aspect_info
|
||||
or not dst_aspect_info.main
|
||||
|
@ -128,7 +131,8 @@ local mainaspects_main = {
|
|||
local applyaspectf_ra = function(rot)
|
||||
-- we get here the full main_aspect table
|
||||
return function(pos, node, main_aspect, dst_aspect, dst_aspect_info)
|
||||
if main_aspect.shunt then
|
||||
if main_aspect then
|
||||
-- any main aspect is fine, there's only one anyway
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:ra_shuntd_"..rot, param2 = node.param2})
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:ra_danger_"..rot, param2 = node.param2})
|
||||
|
@ -144,11 +148,6 @@ local mainaspects_shunt = {
|
|||
description = "Shunt",
|
||||
shunt = true,
|
||||
},
|
||||
{
|
||||
name = "halt",
|
||||
description = "Halt",
|
||||
halt = true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rtab in ipairs({
|
||||
|
@ -225,9 +224,9 @@ for _, rtab in ipairs({
|
|||
apply_aspect = applyaspectf_main(rot),
|
||||
get_aspect_info = afunc,
|
||||
},
|
||||
on_rightclick = advtrains.interlocking.signal_rc_handler,
|
||||
can_dig = advtrains.interlocking.signal_can_dig,
|
||||
after_dig_node = advtrains.interlocking.signal_after_dig,
|
||||
on_rightclick = advtrains.interlocking.signal.on_rightclick,
|
||||
can_dig = advtrains.interlocking.signal.can_dig,
|
||||
after_dig_node = advtrains.interlocking.signal.after_dig,
|
||||
})
|
||||
-- rotatable by trackworker
|
||||
--TODO add rotation using trackworker
|
||||
|
|
Loading…
Reference in New Issue