Signal assignment and route programming procedure
|
@ -133,7 +133,9 @@ end
|
||||||
|
|
||||||
|
|
||||||
function ndb.swap_node(pos, node, no_inval)
|
function ndb.swap_node(pos, node, no_inval)
|
||||||
|
if minetest.get_node_or_nil(pos) then
|
||||||
minetest.swap_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
|
end
|
||||||
ndb.update(pos, node)
|
ndb.update(pos, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -294,6 +296,5 @@ minetest.register_chatcommand("at_sync_ndb",
|
||||||
return true, text
|
return true, text
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
privs = {train_operator=true}, -- Require the "privs" privilege to run
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,8 @@ local ildb = {}
|
||||||
local track_circuit_breaks = {}
|
local track_circuit_breaks = {}
|
||||||
local track_sections = {}
|
local track_sections = {}
|
||||||
|
|
||||||
|
local signal_assignments = {}
|
||||||
|
|
||||||
function ildb.load(data)
|
function ildb.load(data)
|
||||||
if not data then return end
|
if not data then return end
|
||||||
if data.tcbs then
|
if data.tcbs then
|
||||||
|
@ -103,10 +105,13 @@ function ildb.load(data)
|
||||||
if data.ts then
|
if data.ts then
|
||||||
track_sections = data.ts
|
track_sections = data.ts
|
||||||
end
|
end
|
||||||
|
if data.signalass then
|
||||||
|
signal_assignments = data.signalass
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ildb.save()
|
function ildb.save()
|
||||||
return {tcbs = track_circuit_breaks, ts=track_sections}
|
return {tcbs = track_circuit_breaks, ts=track_sections, signalass = signal_assignments}
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -123,6 +128,7 @@ TCB data structure
|
||||||
-- while the signal still displays danger and nothing is written to the TCs
|
-- while the signal still displays danger and nothing is written to the TCs
|
||||||
-- As soon as the route can actually be set, all relevant TCs and turnouts are set and this field
|
-- As soon as the route can actually be set, all relevant TCs and turnouts are set and this field
|
||||||
-- is set true, clearing the signal
|
-- is set true, clearing the signal
|
||||||
|
aspect = <asp> -- The aspect the signal should show. If this is nil, should show the most restrictive aspect (red)
|
||||||
},
|
},
|
||||||
[2] = { -- Variant: end of track-circuited area (initial state of TC)
|
[2] = { -- Variant: end of track-circuited area (initial state of TC)
|
||||||
ts_id = nil, -- this is the indication for end_of_interlocking
|
ts_id = nil, -- this is the indication for end_of_interlocking
|
||||||
|
@ -145,6 +151,11 @@ Track section
|
||||||
|
|
||||||
Signal specifier (sigd) (a pair of TCB/Side):
|
Signal specifier (sigd) (a pair of TCB/Side):
|
||||||
{p = <pos>, s = <1/2>}
|
{p = <pos>, s = <1/2>}
|
||||||
|
|
||||||
|
Signal Assignments: reverse lookup of signals assigned to TCBs
|
||||||
|
signal_assignments = {
|
||||||
|
[<signal pts>] = <sigd>
|
||||||
|
}
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,6 +417,19 @@ function ildb.get_ts_at_pos(pos)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- returns the sigd the signal at pos belongs to, if this is known
|
||||||
|
function ildb.get_sigd_for_signal(pos)
|
||||||
|
local pts = advtrains.roundfloorpts(pos)
|
||||||
|
return signal_assignments[pts]
|
||||||
|
end
|
||||||
|
function ildb.set_sigd_for_signal(pos, sigd)
|
||||||
|
local pts = advtrains.roundfloorpts(pos)
|
||||||
|
signal_assignments[pts] = sigd
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
advtrains.interlocking.db = ildb
|
advtrains.interlocking.db = ildb
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
-- Demonstration signals
|
-- Demonstration signals
|
||||||
-- Those can display the 3 main aspects of Ks signals
|
-- Those can display the 3 main aspects of Ks signals
|
||||||
|
|
||||||
|
-- Note that the group value of advtrains_signal is 2, which means "step 2 of signal capabilities"
|
||||||
|
-- advtrains_signal=1 is meant for signals that do not implement set_aspect.
|
||||||
|
|
||||||
|
|
||||||
minetest.register_node("advtrains_interlocking:ds_danger", {
|
minetest.register_node("advtrains_interlocking:ds_danger", {
|
||||||
description = "Demo signal at Danger",
|
description = "Demo signal at Danger",
|
||||||
tiles = {"at_il_signal_asp_danger.png"},
|
tiles = {"at_il_signal_asp_danger.png"},
|
||||||
groups = {
|
groups = {
|
||||||
cracky = 3,
|
cracky = 3,
|
||||||
advtrains_signal = 1,
|
advtrains_signal = 2,
|
||||||
save_in_at_nodedb = 1,
|
save_in_at_nodedb = 1,
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
@ -35,7 +38,7 @@ minetest.register_node("advtrains_interlocking:ds_free", {
|
||||||
tiles = {"at_il_signal_asp_free.png"},
|
tiles = {"at_il_signal_asp_free.png"},
|
||||||
groups = {
|
groups = {
|
||||||
cracky = 3,
|
cracky = 3,
|
||||||
advtrains_signal = 1,
|
advtrains_signal = 2,
|
||||||
save_in_at_nodedb = 1,
|
save_in_at_nodedb = 1,
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
@ -63,7 +66,7 @@ minetest.register_node("advtrains_interlocking:ds_slow", {
|
||||||
tiles = {"at_il_signal_asp_slow.png"},
|
tiles = {"at_il_signal_asp_slow.png"},
|
||||||
groups = {
|
groups = {
|
||||||
cracky = 3,
|
cracky = 3,
|
||||||
advtrains_signal = 1,
|
advtrains_signal = 2,
|
||||||
save_in_at_nodedb = 1,
|
save_in_at_nodedb = 1,
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
|
|
@ -10,3 +10,4 @@ dofile(modpath.."tcb_ts_ui.lua")
|
||||||
dofile(modpath.."signal_api.lua")
|
dofile(modpath.."signal_api.lua")
|
||||||
dofile(modpath.."demosignals.lua")
|
dofile(modpath.."demosignals.lua")
|
||||||
dofile(modpath.."train_related.lua")
|
dofile(modpath.."train_related.lua")
|
||||||
|
dofile(modpath.."route_prog.lua")
|
||||||
|
|
|
@ -0,0 +1,323 @@
|
||||||
|
-- Route programming system
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Progamming routes:
|
||||||
|
1. Select "program new route" in the signalling dialog
|
||||||
|
-> route_start marker will appear to designate route-program mode
|
||||||
|
2. Do those actions in any order:
|
||||||
|
A. punch a TCB marker node to proceed route along this TCB. This will only work if
|
||||||
|
this is actually a TCB bordering the current TS, and will place a
|
||||||
|
route_set marker and shift to the next TS
|
||||||
|
B. right-click a turnout to switch it (no impact to route programming
|
||||||
|
C. punch a turnout (or some other passive component) to fix its state (toggle)
|
||||||
|
for the route. A sprite telling "Route Fix" will show that fact.
|
||||||
|
3. To complete route setting, use the chat command '/at_program_route <route name>'.
|
||||||
|
The last punched TCB will get a 'route end' marker
|
||||||
|
The end of a route should be at another signal facing the same direction as the entrance signal,
|
||||||
|
however this is not enforced and left up to the signal engineer (the programmer)
|
||||||
|
|
||||||
|
The route visualization will also be used to visualize routes after they have been programmed.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
|
||||||
|
-- table with objectRefs
|
||||||
|
local markerent = {}
|
||||||
|
|
||||||
|
minetest.register_entity("advtrains_interlocking:routemarker", {
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "trackplane.b3d",
|
||||||
|
textures = {"at_il_route_set.png"},
|
||||||
|
collisionbox = {-1,-0.5,-1, 1,-0.4,1},
|
||||||
|
visual_size = {x=10, y=10},
|
||||||
|
on_punch = function(self)
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
get_staticdata = function() return "STATIC" end,
|
||||||
|
on_activate = function(self, sdata) if sdata=="STATIC" then self.object:remove() end end,
|
||||||
|
static_save = false,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Spawn or update a route marker entity
|
||||||
|
-- pos: position where this is going to be
|
||||||
|
-- key: something unique to determine which entity to remove if this was set before
|
||||||
|
-- img: texture
|
||||||
|
local function routemarker(context, pos, key, img, yaw, itex)
|
||||||
|
if not markerent[context] then
|
||||||
|
markerent[context] = {}
|
||||||
|
end
|
||||||
|
if markerent[context][key] then
|
||||||
|
markerent[context][key]:remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
local obj = minetest.add_entity(vector.add(pos, {x=0, y=0.3, z=0}), "advtrains_interlocking:routemarker")
|
||||||
|
if not obj then return end
|
||||||
|
obj:set_yaw(yaw)
|
||||||
|
obj:set_properties({
|
||||||
|
infotext = itex,
|
||||||
|
textures = {img},
|
||||||
|
})
|
||||||
|
|
||||||
|
markerent[context][key] = obj
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("advtrains_interlocking:routesprite", {
|
||||||
|
visual = "sprite",
|
||||||
|
textures = {"at_il_turnout_free.png"},
|
||||||
|
collisionbox = {-0.2,-0.2,-0.2, 0.2,0.2,0.2},
|
||||||
|
visual_size = {x=1, y=1},
|
||||||
|
on_punch = function(self)
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
get_staticdata = function() return "STATIC" end,
|
||||||
|
on_activate = function(self, sdata) if sdata=="STATIC" then self.object:remove() end end,
|
||||||
|
static_save = false,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Spawn or update a route sprite entity
|
||||||
|
-- pos: position where this is going to be
|
||||||
|
-- key: something unique to determine which entity to remove if this was set before
|
||||||
|
-- img: texture
|
||||||
|
local function routesprite(context, pos, key, img, itex)
|
||||||
|
if not markerent[context] then
|
||||||
|
markerent[context] = {}
|
||||||
|
end
|
||||||
|
if markerent[context][key] then
|
||||||
|
markerent[context][key]:remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
local obj = minetest.add_entity(vector.add(pos, {x=0, y=0, z=0}), "advtrains_interlocking:routesprite")
|
||||||
|
if not obj then return end
|
||||||
|
obj:set_properties({
|
||||||
|
infotext = itex,
|
||||||
|
textures = {img},
|
||||||
|
})
|
||||||
|
|
||||||
|
markerent[context][key] = obj
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Route definition:
|
||||||
|
route = {
|
||||||
|
name = <string>
|
||||||
|
tcbpath = {
|
||||||
|
[n] = <sigd>
|
||||||
|
}
|
||||||
|
pcfix = {
|
||||||
|
[<pts>] = "state"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
The first item in the TCB path is always the start signal of this route,
|
||||||
|
so this is left out.
|
||||||
|
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
function advtrains.interlocking.clear_visu_context(context)
|
||||||
|
if not markerent[context] then return end
|
||||||
|
for key, obj in pairs(markerent[context]) do
|
||||||
|
obj:remove()
|
||||||
|
end
|
||||||
|
markerent[context] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- visualize route. 'context' is a string that identifies the context of this visualization
|
||||||
|
-- e.g. prog_<player> or vis<pts> for later visualizations
|
||||||
|
function advtrains.interlocking.visualize_route(origin, route, context)
|
||||||
|
advtrains.interlocking.clear_visu_context(context)
|
||||||
|
for k,sigd in ipairs(route.tcbpath) do
|
||||||
|
local yaw = 0
|
||||||
|
local node_ok, conns, rhe = advtrains.get_rail_info_at(sigd.p, advtrains.all_tracktypes)
|
||||||
|
if node_ok then
|
||||||
|
yaw = advtrains.dir_to_angle(conns[sigd.s].c)
|
||||||
|
end
|
||||||
|
local img = "at_il_route_set.png"
|
||||||
|
if k == #route.tcbpath then img = "at_il_route_end.png" end
|
||||||
|
routemarker(context, sigd.p, "rte"..k, img, yaw, route.name.." #"..k)
|
||||||
|
end
|
||||||
|
for pts, state in pairs(route.pcfix) do
|
||||||
|
local pos = minetest.string_to_pos(pts)
|
||||||
|
routesprite(context, pos, "fix"..pts, "at_il_route_lock.png", "Fixed in state '"..state.."' by route "..route.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local player_rte_prog = {}
|
||||||
|
|
||||||
|
function advtrains.interlocking.init_route_prog(pname, sigd)
|
||||||
|
player_rte_prog[pname] = {
|
||||||
|
origin = sigd,
|
||||||
|
route = {
|
||||||
|
name = "PROG["..pname.."]",
|
||||||
|
tcbpath = {},
|
||||||
|
pcfix = {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
minetest.chat_send_player(pname, "Route programming mode active. Punch TCBs to add route segments, punch turnouts to lock them.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_last_route_item(origin, route)
|
||||||
|
if #route.tcbpath == 0 then
|
||||||
|
return origin
|
||||||
|
end
|
||||||
|
return route.tcbpath[#route.tcbpath]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function chat(pname, message)
|
||||||
|
minetest.chat_send_player(pname, "[Route programming] "..message)
|
||||||
|
end
|
||||||
|
local function otherside(s)
|
||||||
|
if s==1 then return 2 else return 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Central route programming punch callback
|
||||||
|
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
|
local pname = player:get_player_name()
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if rp then
|
||||||
|
-- determine what the punched node is
|
||||||
|
if minetest.get_item_group(node.name, "at_il_track_circuit_break") >= 1 then
|
||||||
|
-- get position of the assigned tcb
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local tcbpts = meta:get_string("tcb_pos")
|
||||||
|
if tcbpts == "" then
|
||||||
|
chat(pname, "This TCB is unconfigured, you first need to assign it to a rail")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local tcbpos = minetest.string_to_pos(tcbpts)
|
||||||
|
|
||||||
|
-- track circuit break, try to advance route over it
|
||||||
|
local lri = get_last_route_item(rp.origin, rp.route)
|
||||||
|
if vector.equals(lri.p, tcbpos) then
|
||||||
|
chat(pname, "You cannot continue the route to where you came from!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local start_tcbs = advtrains.interlocking.db.get_tcbs(lri)
|
||||||
|
if not start_tcbs.ts_id then
|
||||||
|
chat(pname, "The previous TCB was End of Interlocking. Please complete route programming using '/at_rp_set <name>'")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local ts = advtrains.interlocking.db.get_ts(start_tcbs.ts_id)
|
||||||
|
if not ts then atwarn("Internal error, ts inexistant for id!") return end
|
||||||
|
local found = nil
|
||||||
|
for _,sigd in ipairs(ts.tc_breaks) do
|
||||||
|
if vector.equals(sigd.p, tcbpos) then
|
||||||
|
found = otherside(sigd.s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not found then
|
||||||
|
chat(pname, "Previous and this TCB belong to different track sections!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- everything worked, just add the other side to the list
|
||||||
|
table.insert(rp.route.tcbpath, {p = tcbpos, s = found})
|
||||||
|
chat(pname, "Added track section '"..ts.name.."' to the route (revert with /at_rp_back)")
|
||||||
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ndef = minetest.registered_nodes[node.name]
|
||||||
|
if ndef and ndef.luaautomation and ndef.luaautomation.getstate then
|
||||||
|
local pts = advtrains.roundfloorpts(pos)
|
||||||
|
if rp.route.pcfix[pts] then
|
||||||
|
rp.route.pcfix[pts] = nil
|
||||||
|
chat(pname, pts.." is no longer affected when this route is set.")
|
||||||
|
else
|
||||||
|
local state = ndef.luaautomation.getstate
|
||||||
|
if type(state)=="function" then
|
||||||
|
state = state(pos, node)
|
||||||
|
end
|
||||||
|
rp.route.pcfix[pts] = state
|
||||||
|
chat(pname, pts.." is held in "..state.." position when this route is set.")
|
||||||
|
end
|
||||||
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_chatcommand("at_rp_set",
|
||||||
|
{
|
||||||
|
params = "<name>", -- Short parameter description
|
||||||
|
description = "Completes route programming procedure", -- Full description
|
||||||
|
privs = {}, -- TODO
|
||||||
|
func = function(pname, param)
|
||||||
|
return advtrains.pcall(function()
|
||||||
|
if param=="" then
|
||||||
|
return false, "Missing name parameter!"
|
||||||
|
end
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if rp then
|
||||||
|
if #rp.route.tcbpath <= 0 then
|
||||||
|
return false, "Cannot program route without a target"
|
||||||
|
end
|
||||||
|
rp.route.name = param
|
||||||
|
-- TODO save that route somewhere in origin
|
||||||
|
atdebug("ROUTE RESULT:",rp)
|
||||||
|
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
||||||
|
return true, "Successfully programmed route"
|
||||||
|
end
|
||||||
|
return false, "You were not programming a route!"
|
||||||
|
end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("at_rp_back",
|
||||||
|
{
|
||||||
|
params = "", -- Short parameter description
|
||||||
|
description = "Remove last route segment", -- Full description
|
||||||
|
privs = {}, -- Require the "privs" privilege to run
|
||||||
|
func = function(pname, param)
|
||||||
|
return advtrains.pcall(function()
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if rp then
|
||||||
|
if #rp.route.tcbpath <= 0 then
|
||||||
|
return false, "Cannot backtrack when there are no route elements"
|
||||||
|
end
|
||||||
|
rp.route.tcbpath[#rp.route.tcbpath] = nil
|
||||||
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
||||||
|
return true, "Route section "..(#rp.route.tcbpath+1).." removed."
|
||||||
|
end
|
||||||
|
return false, "You were not programming a route!"
|
||||||
|
end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("at_rp_mark",
|
||||||
|
{
|
||||||
|
params = "", -- Short parameter description
|
||||||
|
description = "Re-set route programming markers", -- Full description
|
||||||
|
privs = {}, -- TODO
|
||||||
|
func = function(pname, param)
|
||||||
|
return advtrains.pcall(function()
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if rp then
|
||||||
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
||||||
|
return true, "Redrawn route markers"
|
||||||
|
end
|
||||||
|
return false, "You were not programming a route!"
|
||||||
|
end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_chatcommand("at_rp_discard",
|
||||||
|
{
|
||||||
|
params = "", -- Short parameter description
|
||||||
|
description = "Discards the currently programmed route", -- Full description
|
||||||
|
privs = {}, -- Require the "privs" privilege to run
|
||||||
|
func = function(pname, param)
|
||||||
|
return advtrains.pcall(function()
|
||||||
|
player_rte_prog[pname] = nil
|
||||||
|
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
||||||
|
return true, "Route discarded"
|
||||||
|
end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
--TODO on route setting
|
||||||
|
-- locked turnouts need to somehow know the TS they're associated to, which isn't possible with the current route programming and saving method
|
||||||
|
-- unify luaautomation get/setstate interface to the core
|
||||||
|
-- privileges for route programming
|
||||||
|
-- for now, that locking aspect will be ignored and turnouts just set when route gets commited.
|
|
@ -33,6 +33,21 @@ on_rightclick = advtrains.interlocking.signal_rc_handler
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
local DANGER = {
|
||||||
|
main = {
|
||||||
|
free = false,
|
||||||
|
speed = 0,
|
||||||
|
},
|
||||||
|
shunt = {
|
||||||
|
free = false,
|
||||||
|
},
|
||||||
|
dst = {
|
||||||
|
free = false,
|
||||||
|
speed = 0,
|
||||||
|
},
|
||||||
|
info = {}
|
||||||
|
}
|
||||||
|
|
||||||
function advtrains.interlocking.signal_set_aspect(pos, asp)
|
function advtrains.interlocking.signal_set_aspect(pos, asp)
|
||||||
local node=advtrains.ndb.get_node(pos)
|
local node=advtrains.ndb.get_node(pos)
|
||||||
local ndef=minetest.registered_nodes[node.name]
|
local ndef=minetest.registered_nodes[node.name]
|
||||||
|
@ -43,8 +58,14 @@ end
|
||||||
|
|
||||||
function advtrains.interlocking.signal_rc_handler(pos, node, player, itemstack, pointed_thing)
|
function advtrains.interlocking.signal_rc_handler(pos, node, player, itemstack, pointed_thing)
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
|
local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||||
|
if sigd then
|
||||||
|
advtrains.interlocking.show_signalling_form(sigd, pname)
|
||||||
|
else
|
||||||
|
-- permit to set aspect manually
|
||||||
minetest.show_formspec(pname, "at_il_sigasp_"..minetest.pos_to_string(pos), "field[aspect;Set Aspect (F/D)Speed(F/D)Speed(F/D);D0D0D]")
|
minetest.show_formspec(pname, "at_il_sigasp_"..minetest.pos_to_string(pos), "field[aspect;Set Aspect (F/D)Speed(F/D)Speed(F/D);D0D0D]")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
|
@ -73,3 +94,15 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
advtrains.interlocking.signal_set_aspect(pos, asp)
|
advtrains.interlocking.signal_set_aspect(pos, asp)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Returns the aspect the signal at pos is supposed to show
|
||||||
|
function advtrains.interlocking.signal_get_aspect(pos)
|
||||||
|
local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos)
|
||||||
|
if sigd then
|
||||||
|
local tcbs = advtrains.interlocking.db.get_tcbs(sigd)
|
||||||
|
if tcbs.aspect then
|
||||||
|
return tcbs.aspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return DANGER;
|
||||||
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
-- Track Circuit Breaks and Track Sections - Player interaction
|
-- Track Circuit Breaks and Track Sections - Player interaction
|
||||||
|
|
||||||
local players_assign_tcb = {}
|
local players_assign_tcb = {}
|
||||||
|
local players_assign_signal = {}
|
||||||
local players_link_ts = {}
|
local players_link_ts = {}
|
||||||
|
|
||||||
local lntrans = { "A", "B" }
|
local lntrans = { "A", "B" }
|
||||||
|
@ -26,6 +27,7 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
|
||||||
cracky=3,
|
cracky=3,
|
||||||
not_blocking_trains=1,
|
not_blocking_trains=1,
|
||||||
--save_in_at_nodedb=2,
|
--save_in_at_nodedb=2,
|
||||||
|
at_il_track_circuit_break = 1,
|
||||||
},
|
},
|
||||||
after_place_node = function(pos, node, player)
|
after_place_node = function(pos, node, player)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
|
@ -46,14 +48,14 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
|
||||||
players_assign_tcb[pname] = pos
|
players_assign_tcb[pname] = pos
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_punch = function(pos, node, player)
|
--on_punch = function(pos, node, player)
|
||||||
local meta = minetest.get_meta(pos)
|
-- local meta = minetest.get_meta(pos)
|
||||||
local tcbpts = meta:get_string("tcb_pos")
|
-- local tcbpts = meta:get_string("tcb_pos")
|
||||||
if tcbpts ~= "" then
|
-- if tcbpts ~= "" then
|
||||||
local tcbpos = minetest.string_to_pos(tcbpts)
|
-- local tcbpos = minetest.string_to_pos(tcbpts)
|
||||||
advtrains.interlocking.show_tcb_marker(tcbpos)
|
-- advtrains.interlocking.show_tcb_marker(tcbpos)
|
||||||
end
|
-- end
|
||||||
end,
|
--end,
|
||||||
can_dig = function(pos, player)
|
can_dig = function(pos, player)
|
||||||
-- Those markers can only be dug when all adjacent TS's are set
|
-- Those markers can only be dug when all adjacent TS's are set
|
||||||
-- as EOI.
|
-- as EOI.
|
||||||
|
@ -83,6 +85,7 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
|
||||||
|
|
||||||
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
|
-- TCB assignment
|
||||||
local tcbnpos = players_assign_tcb[pname]
|
local tcbnpos = players_assign_tcb[pname]
|
||||||
if tcbnpos then
|
if tcbnpos then
|
||||||
if vector.distance(pos, tcbnpos)<=20 then
|
if vector.distance(pos, tcbnpos)<=20 then
|
||||||
|
@ -109,6 +112,29 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
end
|
end
|
||||||
players_assign_tcb[pname] = nil
|
players_assign_tcb[pname] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Signal assignment
|
||||||
|
local sigd = players_assign_signal[pname]
|
||||||
|
if sigd then
|
||||||
|
if vector.distance(pos, sigd.p)<=50 then
|
||||||
|
local is_signal = minetest.get_item_group(node.name, "advtrains_signal") >= 2
|
||||||
|
if is_signal then
|
||||||
|
local tcbs = advtrains.interlocking.db.get_tcbs(sigd)
|
||||||
|
if tcbs then
|
||||||
|
tcbs.signal = pos
|
||||||
|
advtrains.interlocking.db.set_sigd_for_signal(pos, sigd)
|
||||||
|
minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.")
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(pname, "Configuring TCB: Internal error, TCBS doesn't exist. Aborted.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(pname, "Configuring TCB: Not a compatible signal. Aborted.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minetest.chat_send_player(pname, "Configuring TCB: Node is too far away. Aborted.")
|
||||||
|
end
|
||||||
|
players_assign_tcb[pname] = nil
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,6 +161,11 @@ local function mktcbformspec(tcbs, btnpref, offset, pname)
|
||||||
form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setfree;Section is blocked]"
|
form = form.."button[0.5,"..(offset+1.5)..";5,1;"..btnpref.."_setfree;Section is blocked]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if tcbs.signal then
|
||||||
|
form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_sigdia;Signalling]"
|
||||||
|
else
|
||||||
|
form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_asnsig;Assign a signal]"
|
||||||
|
end
|
||||||
return form
|
return form
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -143,9 +174,9 @@ function advtrains.interlocking.show_tcb_form(pos, pname)
|
||||||
local tcb = advtrains.interlocking.db.get_tcb(pos)
|
local tcb = advtrains.interlocking.db.get_tcb(pos)
|
||||||
if not tcb then return end
|
if not tcb then return end
|
||||||
|
|
||||||
local form = "size[6,7] label[0.5,0.5;Track Circuit Break Configuration]"
|
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[1], "A", 1, pname)
|
||||||
form = form .. mktcbformspec(tcb[2], "B", 4, pname)
|
form = form .. mktcbformspec(tcb[2], "B", 5, pname)
|
||||||
|
|
||||||
minetest.show_formspec(pname, "at_il_tcbconfig_"..minetest.pos_to_string(pos), form)
|
minetest.show_formspec(pname, "at_il_tcbconfig_"..minetest.pos_to_string(pos), form)
|
||||||
advtrains.interlocking.show_tcb_marker(pos)
|
advtrains.interlocking.show_tcb_marker(pos)
|
||||||
|
@ -174,6 +205,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
local f_makeil = {fields.A_makeil, fields.B_makeil}
|
local f_makeil = {fields.A_makeil, fields.B_makeil}
|
||||||
local f_setlocked = {fields.A_setlocked, fields.B_setlocked}
|
local f_setlocked = {fields.A_setlocked, fields.B_setlocked}
|
||||||
local f_setfree = {fields.A_setfree, fields.B_setfree}
|
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}
|
||||||
|
|
||||||
for connid=1,2 do
|
for connid=1,2 do
|
||||||
local tcbs = tcb[connid]
|
local tcbs = tcb[connid]
|
||||||
|
@ -201,6 +234,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
tcbs.section_free = nil
|
tcbs.section_free = nil
|
||||||
end
|
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.")
|
||||||
|
players_assign_signal[pname] = {p=pos, s=connid}
|
||||||
|
minetest.close_formspec(pname, formname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if f_sigdia[connid] and tcbs.signal then
|
||||||
|
advtrains.interlocking.show_signalling_form({p=pos, s=connid}, pname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
advtrains.interlocking.show_tcb_form(pos, pname)
|
advtrains.interlocking.show_tcb_form(pos, pname)
|
||||||
end
|
end
|
||||||
|
@ -373,3 +417,33 @@ function advtrains.interlocking.show_tcb_marker(pos)
|
||||||
|
|
||||||
markerent[pts] = obj
|
markerent[pts] = obj
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Signalling formspec - set routes a.s.o
|
||||||
|
|
||||||
|
function advtrains.interlocking.show_signalling_form(sigd, pname)
|
||||||
|
local form = "size[10,10]label[0.5,0.5;Track Section Detail - ]"
|
||||||
|
form = form.."field[0.8,2;5.2,1;name;Section name;]"
|
||||||
|
form = form.."button[5.5,1.7;1,1;setname;Set]"
|
||||||
|
|
||||||
|
--minetest.show_formspec(pname, "at_il_signalling_"..sigd.p.."_"..sigd.s, form)
|
||||||
|
--TODO this is temporary
|
||||||
|
advtrains.interlocking.init_route_prog(pname, sigd)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
|
local pname = player:get_player_name()
|
||||||
|
local pts, connids = string.match(formname, "^at_il_signalling_([^_]+)_(%d)$")
|
||||||
|
local pts = string.match(formname, "^at_il_tcbconfig_(.+)$")
|
||||||
|
local pos, connid
|
||||||
|
if pts then
|
||||||
|
pos = minetest.string_to_pos(pts)
|
||||||
|
connid = tonumber(connids)
|
||||||
|
if not connid or connid<1 or connid>2 then return end
|
||||||
|
end
|
||||||
|
if pos and connid and not fields.quit then
|
||||||
|
|
||||||
|
advtrains.interlocking.show_signalling_form(ts_id, pname, sel_tcb)
|
||||||
|
end
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 398 B |
After Width: | Height: | Size: 380 B |
After Width: | Height: | Size: 314 B |
After Width: | Height: | Size: 298 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 229 B |