aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--advtrains_line_automation/init.lua2
-rw-r--r--advtrains_line_automation/line_functions.lua115
-rw-r--r--advtrains_line_automation/mod.conf4
-rw-r--r--advtrains_line_automation/models/advtrains_tuber.obj152
-rw-r--r--advtrains_line_automation/models/license.txt5
-rw-r--r--advtrains_line_automation/station_announcement.lua748
-rw-r--r--advtrains_line_automation/structs.md39
7 files changed, 990 insertions, 75 deletions
diff --git a/advtrains_line_automation/init.lua b/advtrains_line_automation/init.lua
index 2d4a97e..fbf1d8d 100644
--- a/advtrains_line_automation/init.lua
+++ b/advtrains_line_automation/init.lua
@@ -24,7 +24,7 @@ dofile(modpath.."line_editor.lua")
dofile(modpath.."scheduler.lua")
dofile(modpath.."station_editor.lua")
dofile(modpath.."stoprail.lua")
--- dofile(modpath.."station_announcement.lua")
+dofile(modpath.."station_announcement.lua")
function advtrains.lines.load(data)
if data then
diff --git a/advtrains_line_automation/line_functions.lua b/advtrains_line_automation/line_functions.lua
index 0a4e6d2..6f60ab5 100644
--- a/advtrains_line_automation/line_functions.lua
+++ b/advtrains_line_automation/line_functions.lua
@@ -59,6 +59,7 @@ local function get_station_name(stn)
return "???"
end
end
+al.get_station_name = get_station_name
local function na_velka_pismena(s)
local l = #s
@@ -130,6 +131,7 @@ local function get_first_last_stations(linevar_def)
end
end
end
+ print("get_first_last_stations(): "..dump2({i_first = i_first, i_last = i_last, i_firstx = i_firstx, i_lastx = i_lastx, stops = stops}))
if i_first ~= nil and i_last ~= nil then
return stops[i_first].stn, stops[i_last].stn
elseif i_firstx ~= nil and i_lastx ~= nil then
@@ -299,11 +301,31 @@ end
--[[
Vrací:
+ a) index, stop_data -- pokud byla vyhovující předchozí zastávka nalezena
+ b) nil, nil -- pokud nalezena nebyla
+]]
+function al.get_prev_stop(linevar_def, current_index, allow_hidden_stops)
+ local stops = assert(linevar_def.stops)
+ assert(current_index)
+ if current_index > 1 then
+ for i = current_index - 1, 1, -1 do
+ local mode = stops[i].mode
+ if mode == nil or (mode ~= MODE_DISABLED and ((mode ~= MODE_HIDDEN and mode ~= MODE_FINAL_HIDDEN) or allow_hidden_stops)) then
+ return i, stops[i]
+ end
+ end
+ end
+ return nil, nil
+end
+
+--[[
+ Vrací:
a) index, stop_data -- pokud byla vyhovující další zastávka nalezena
b) nil, nil -- pokud nalezena nebyla
]]
function al.get_next_stop(linevar_def, current_index, allow_hidden_stops)
local stops = assert(linevar_def.stops)
+ assert(current_index)
if current_index < #stops then
for i = current_index + 1, #stops do
local mode = stops[i].mode
@@ -321,16 +343,22 @@ end
b) nil, nil -- pokud nalezena nebyla
]]
function al.get_terminus(linevar_def, current_index, allow_hidden_stops)
+ print("DEBUG: get_terminus() called: "..dump2({linevar_def, current_index, allow_hidden_stops}))
local stops = assert(linevar_def.stops)
+ local r_i, r_stop
if current_index < #stops then
for i = current_index + 1, #stops do
- local mode = stops[i].mode
- if mode ~= nil and (mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE or (mode == MODE_FINAL_HIDDEN and allow_hidden_stops)) then
- return i, stops[i]
+ local mode = stops[i].mode or MODE_NORMAL
+ print("DEBUG: stop mode at index "..i.." is "..(mode or MODE_NORMAL))
+ if mode ~= MODE_DISABLED and ((mode ~= MODE_HIDDEN and mode ~= MODE_FINAL_HIDDEN) or allow_hidden_stops) then
+ r_i, r_stop = i, stops[i]
+ end
+ if mode == MODE_FINAL or mode == MODE_FINAL_CONTINUE or mode == MODE_FINAL_HIDDEN then
+ break
end
end
end
- return nil, nil
+ return r_i, r_stop
end
--[[
@@ -929,6 +957,15 @@ local function get_last_pos(line_status)
return result
end
+function al.get_last_pos_station_name(line_status)
+ local result = get_last_pos(line_status)
+ if result.type ~= "none" then
+ return get_station_name(result.last_pos.stn)
+ else
+ return nil
+ end
+end
+
local function get_train_position(line_status, linevar_def, rwtime)
if line_status ~= nil then
local last_pos_info = get_last_pos(line_status)
@@ -948,6 +985,76 @@ local function get_train_position(line_status, linevar_def, rwtime)
return "???"
end
+--[[
+ Zadaný vlak musí být linkový.
+ Vrací:
+ {stn = string, track = string, stdata = table or nil, dep = int or nil, arr = int or nil, delay = int}
+]]
+function al.predict_train(line_status, linevar_def, rwtime)
+ assert(line_status)
+ assert(linevar_def)
+ local stops = linevar_def.stops
+ local result = {}
+ local index = assert(line_status.linevar_index)
+ if rwtime == nil then
+ rwtime = rwt.to_secs(rwt.get_time())
+ end
+ local delay_desc = al.get_delay_description(line_status, linevar_def, rwtime)
+ local delay
+ if delay_desc.has_delay then
+ delay = delay_desc.delay
+ else
+ delay = 0
+ end
+ if line_status.standing_at ~= nil then
+ -- vlak stojí na zastávce
+ local stop = assert(stops[index])
+ local stdata = advtrains.lines.stations[stop.stn]
+ table.insert(result, {
+ stn = line_status.linevar_last_stn,
+ track = stop.track or "",
+ stdata = stdata,
+ dep = assert(line_status.linevar_last_dep),
+ -- arr = nil,
+ delay = delay,
+ index = index,
+ hidden = stop.mode == MODE_HIDDEN
+ })
+ end
+ index = index + 1
+ while stops[index] ~= nil do
+ local stop = stops[index]
+ local stdata = advtrains.lines.stations[stop.stn]
+ if stop.mode == MODE_FINAL or stop.mode == MODE_FINAL_CONTINUE or stop.mode == MODE_FINAL_HIDDEN then
+ -- koncová zastávka
+ table.insert(result, {
+ stn = assert(stop.stn),
+ track = stop.track or "",
+ stdata = stdata,
+ arr = line_status.linevar_dep + stop.dep + delay,
+ delay = delay,
+ index = index,
+ hidden = stop.mode == MODE_FINAL_HIDDEN,
+ })
+ break
+ elseif stop.mode ~= MODE_DISABLED then
+ -- mezilehlá zastávka
+ table.insert(result, {
+ stn = assert(stop.stn),
+ track = stop.track or "",
+ stdata = stdata,
+ arr = line_status.linevar_dep + stop.dep + delay, -- TODO...
+ dep = line_status.linevar_dep + stop.dep + delay,
+ delay = delay,
+ index = index,
+ hidden = stop.mode == MODE_HIDDEN,
+ })
+ end
+ index = index + 1
+ end
+ return result
+end
+
local function vlaky(param, past_trains_too)
local result = {}
if param:match("/") then
diff --git a/advtrains_line_automation/mod.conf b/advtrains_line_automation/mod.conf
index 9d6e9e8..eeae5a2 100644
--- a/advtrains_line_automation/mod.conf
+++ b/advtrains_line_automation/mod.conf
@@ -3,5 +3,5 @@ title=Advanced Trains Line Automation
description=Tools for automatic train lines
author=orwell96
-depends=advtrains_interlocking
-optional_depends=advtrains_train_track,ch_time
+depends=advtrains_interlocking,default
+optional_depends=advtrains_train_track,ch_time,signs_api,unifieddyes
diff --git a/advtrains_line_automation/models/advtrains_tuber.obj b/advtrains_line_automation/models/advtrains_tuber.obj
new file mode 100644
index 0000000..25bc6dc
--- /dev/null
+++ b/advtrains_line_automation/models/advtrains_tuber.obj
@@ -0,0 +1,152 @@
+# Blender v2.76 (sub 0) OBJ File: 'dark_tuber.blend'
+# www.blender.org
+mtllib underch_dark_tuber.mtl
+o Cube
+v 0.136329 -0.157988 0.702133
+v 0.136329 0.157988 0.702133
+v -0.136329 0.157988 0.702133
+v -0.136329 -0.157988 0.702133
+v 0.368861 -0.368861 -0.337695
+v 0.368861 0.368862 -0.466279
+v -0.381520 0.360664 -0.354918
+v -0.368861 -0.368861 -0.057503
+v 0.223277 -0.225624 0.028756
+v 0.216947 0.221525 0.018022
+v -0.262021 0.200536 -0.023957
+v -0.229606 -0.229722 0.156757
+v 0.100830 -0.108796 0.403707
+v 0.100830 0.108796 0.432070
+v -0.117708 0.097867 0.380743
+v -0.100830 -0.108796 0.439469
+v 0.264026 -0.267600 0.054980
+v 0.264026 0.267600 -0.003499
+v -0.264026 0.267600 0.054980
+v -0.264026 -0.267600 0.211890
+v 0.000000 -0.157988 0.702133
+v 0.000000 -0.461012 -0.167161
+v 0.000000 -0.263640 0.098449
+v 0.000000 -0.131624 0.421588
+v 0.000000 -0.316408 0.141084
+v -0.000000 0.157988 0.702133
+v -0.006330 0.456914 -0.441037
+v -0.025702 0.246997 -0.008661
+v -0.008439 0.126160 0.406407
+v -0.000000 0.316408 0.018092
+v -0.136329 -0.000000 0.702133
+v -0.467342 -0.004099 -0.175772
+v -0.286994 -0.016643 0.063482
+v -0.128968 -0.005465 0.410106
+v -0.312834 -0.000000 0.141084
+v 0.136329 0.000000 0.702133
+v 0.461012 0.000000 -0.432425
+v 0.261292 0.000000 0.026307
+v 0.120528 0.000000 0.417888
+v 0.312834 0.000000 0.018092
+vt 1.000000 1.000000
+vt 0.937500 1.000000
+vt 0.875000 1.000000
+vt 0.875000 0.937500
+vt 0.875000 0.875000
+vt 0.937500 0.875000
+vt 1.000000 0.875000
+vt 1.000000 0.937500
+vt 0.750000 1.000000
+vt 0.750000 0.500000
+vt 0.875000 0.500000
+vt 0.625000 0.500000
+vt 0.625000 1.000000
+vt 0.500000 1.000000
+vt 0.500000 0.500000
+vt 0.375000 0.500000
+vt 0.375000 1.000000
+vt 0.250000 1.000000
+vt 0.250000 0.500000
+vt 0.125000 0.500000
+vt 0.125000 1.000000
+vt -0.000000 1.000000
+vt 0.000000 0.500000
+vt 0.875000 -0.000000
+vt 1.000000 0.000000
+vt 1.000000 0.500000
+vt 1.000000 0.750000
+vt 1.000000 0.812500
+vt 0.875000 0.812500
+vt 0.875000 0.750000
+vt 0.937500 0.750000
+vt 0.125000 -0.000000
+vt -0.000000 -0.000000
+vt 0.375000 -0.000000
+vt 0.250000 -0.000000
+vt 0.625000 0.000000
+vt 0.500000 -0.000000
+vt 0.750000 0.000000
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+vn 0.3128 0.0000 0.0181
+usemtl Material
+s off
+f 1/1/1 36/2/1 2/3/1 26/4/1 3/5/1 31/6/1 4/7/1 21/8/1
+f 32/3/2 7/9/2 11/10/2 33/11/2
+f 40/12/3 37/13/3 6/14/3 18/15/3
+f 30/16/4 27/17/4 7/18/4 19/19/4
+f 35/20/5 32/21/5 8/22/5 20/23/5
+f 25/11/6 21/24/6 4/25/6 20/26/6
+f 22/21/7 8/22/7 12/23/7 23/20/7
+f 27/13/8 6/14/8 10/15/8 28/12/8
+f 37/17/9 5/18/9 9/19/9 38/16/9
+f 13/27/10 24/28/10 16/7/10 34/6/10 15/5/10 29/29/10 14/30/10 39/31/10
+f 22/3/11 25/11/11 20/26/11 8/1/11
+f 31/32/12 35/20/12 20/23/12 4/33/12
+f 26/34/13 30/16/13 19/19/13 3/35/13
+f 36/36/14 40/12/14 18/15/14 2/37/14
+f 28/12/15 10/15/15 14/37/15 29/36/15
+f 38/16/16 9/19/16 13/35/16 39/34/16
+f 33/11/17 11/10/17 15/38/17 34/24/17
+f 23/20/18 12/23/18 16/33/18 24/32/18
+f 9/19/19 23/20/19 24/32/19 13/35/19
+f 5/9/20 17/10/20 25/11/20 22/3/20
+f 5/18/21 22/21/21 23/20/21 9/19/21
+f 17/10/22 1/38/22 21/24/22 25/11/22
+f 11/10/23 28/12/23 29/36/23 15/38/23
+f 2/37/24 18/15/24 30/16/24 26/34/24
+f 7/9/25 27/13/25 28/12/25 11/10/25
+f 18/15/26 6/14/26 27/17/26 30/16/26
+f 12/26/27 33/11/27 34/24/27 16/25/27
+f 3/35/28 19/19/28 35/20/28 31/32/28
+f 19/19/29 7/18/29 32/21/29 35/20/29
+f 8/1/30 32/3/30 33/11/30 12/26/30
+f 10/15/31 38/16/31 39/34/31 14/37/31
+f 1/38/32 17/10/32 40/12/32 36/36/32
+f 6/14/33 37/17/33 38/16/33 10/15/33
+f 17/10/34 5/9/34 37/13/34 40/12/34
diff --git a/advtrains_line_automation/models/license.txt b/advtrains_line_automation/models/license.txt
new file mode 100644
index 0000000..dae06a8
--- /dev/null
+++ b/advtrains_line_automation/models/license.txt
@@ -0,0 +1,5 @@
+advtrains_tuber.obj
+ Author: Hume2
+ Source: https://gitlab.com/h2mm/underch underch_dark_tuber.obj (Underground Challenge)
+ Modified (rotated)
+ License: CC0
diff --git a/advtrains_line_automation/station_announcement.lua b/advtrains_line_automation/station_announcement.lua
index c20fa3c..ef4fc01 100644
--- a/advtrains_line_automation/station_announcement.lua
+++ b/advtrains_line_automation/station_announcement.lua
@@ -1,6 +1,14 @@
-local def
+local al = advtrains.lines
local F = core.formspec_escape
local ifthenelse = assert(ch_core.ifthenelse)
+local rwt = assert(advtrains.lines.rwt)
+local def
+local function CF(s)
+ if s ~= nil then return F(s) else return "" end
+end
+local has_signs_api = core.get_modpath("signs_api")
+local has_unifieddyes = core.get_modpath("unifieddyes")
+local rozhlas_node_name = "advtrains_line_automation:stanicni_rozhlas_experimental"
local PAGE_SETUP_1 = 1
local PAGE_SETUP_2 = 2
@@ -75,32 +83,64 @@ local hl_texty_id_to_idx = function()
end
hl_texty_id_to_idx = hl_texty_id_to_idx()
+local punch_context = {--[[
+ [player_name] = {
+ stn = string,
+ epos = string,
+ i = int,
+ }
+]]}
+
local function dist2(a, b)
local x, y, z = a.x - b.x, a.y - b.y, a.z - b.z
return x * x + y * y + z * z
end
+local function goa(t, k) -- goa = get or add
+ local result = t[k]
+ if result == nil then
+ result = {}
+ t[k] = result
+ end
+ return result
+end
+
--[[
Vrací:
- success = bool
- min = int or nil (pro success == false vždy nil)
- max = int or nil (pro success == false vždy nil)
+ - align = "left" or "right" or "center"
]]
local function lengths_from_string(s)
if s == "" or s == "-" then
return true, nil, nil
end
+ local l = #s
+ s = s:gsub("^ +", "")
+ local left = #s < l
+ l = #s
+ s = s:gsub(" +$", "")
+ local right = #s < l
+ local align
+ if not left then
+ align = "left" -- mezery vpravo, nebo žádné mezery
+ elseif right then
+ align = "center" -- mezery na obou stranách
+ else
+ align = "right" -- mezery jen vlevo
+ end
local n = s:match("^%d+$")
if n ~= nil then
n = assert(tonumber(n))
if n > 256 then
n = 256
end
- return true, n, n
+ return true, n, n, align
end
local min, max = s:match("^(%d*)-(%d*)$")
if min == nil then
- return false, nil, nil -- bad format
+ return false, nil, nil, nil -- bad format
end
min, max = tonumber(min), tonumber(max)
if min ~= nil and min > 256 then min = 256 end
@@ -108,9 +148,10 @@ local function lengths_from_string(s)
if min ~= nil and max ~= nil and min > max then
min = max
end
- return true, min, max
+ return true, min, max, align
end
+--[[ (obsolete)
local function lengths_to_string(min, max)
if min == nil then
if max ~= nil then
@@ -126,6 +167,7 @@ local function lengths_to_string(min, max)
return min.."-"..max
end
end
+]]
local alphanum_chars_set = {
["a"] = true, ["A"] = true, ["á"] = true, ["Á"] = true, ["ä"] = true, ["Ä"] = true, ["b"] = true, ["B"] = true, ["č"] = true,
@@ -163,22 +205,32 @@ local function dosadit(format, data, defaults)
break
end
local tag = format:sub(b + 1, e - 1)
+ local tag_name = tag
local tagfmt, tagalt = ""
- local j = tag:find("|", 1, true)
- if j ~= nil then
- tagalt = tag:sub(j + 1, -1)
- tag = tag:sub(1, j - 1)
- end
- j = tag:find(":", 1, true)
- if j ~= nil then
- tagfmt = tag:sub(j + 1, -1)
- tag = tag:sub(1, j - 1)
+ local b2 = tag:find("[:|]")
+ if b2 == nil then
+ tag_name, tagfmt = tag, ""
+ else
+ tag_name = tag:sub(1, b2 - 1)
+ repeat
+ local e2 = tag:find("[:|]", b2 + 1) or (#tag + 1)
+ print("DEBUG: b2 == "..b2.." e2 = "..e2.." #tag = "..#tag)
+ local c = tag:sub(b2, b2)
+ if c == ":" then
+ tagfmt = tag:sub(b2 + 1, e2 - 1)
+ elseif c == "|" then
+ tagalt = tag:sub(b2 + 1, e2 - 1)
+ end
+ b2 = e2
+ until b2 >= #tag
end
- local min, max
+ local min, max, align
if tagfmt ~= "" then
local success
- success, min, max = lengths_from_string(tagfmt)
+ success, min, max, align = lengths_from_string(tagfmt)
end
+ tag = tag_name
+ -- print("DEBUG: tag("..tag..") tagname("..tag_name..")")
if tag:len() < 4 and ch_core.utf8_length(tag) == 1 and alphanum_chars_set[tag] == nil then
-- speciální případ: zopakovat znak alespoň min-krát
if min ~= nil then
@@ -190,20 +242,59 @@ local function dosadit(format, data, defaults)
local value = data[tag] or tagalt or defaults[tag] or "ERR"
local len = ch_core.utf8_length(value)
if min ~= nil and len < min then
- table.insert(result, value)
- table.insert(result, string.rep(" ", min - len))
+ -- řetězec je kratší než minimum => prodloužit
+ local missing = min - len
+ if align == "left" then
+ table.insert(result, value)
+ table.insert(result, string.rep(" ", missing))
+ elseif align == "right" then
+ table.insert(result, string.rep(" ", missing))
+ table.insert(result, value)
+ else
+ table.insert(result, string.rep(" ", math.floor(missing / 2)))
+ table.insert(result, value)
+ table.insert(result, string.rep(" ", missing - math.floor(missing / 2)))
+ print("DEBUG: value \""..value.."\" align(center) min("..min..") => \""..string.rep(" ", math.floor(missing / 2))..value..string.rep(" ", missing - math.floor(missing / 2)).."\"")
+ end
elseif max ~= nil and len > max then
- table.insert(result, ch_core.utf8_truncate_right(value, max))
+ -- řetězec je delší než maximum => oříznout
+ if align == "left" then
+ local pos = assert(ch_core.utf8_seek(value, 1, max))
+ table.insert(result, value:sub(1, pos - 1))
+ print("DEBUG: value \""..value.."\" align(left) max("..max..") => \""..value:sub(1, pos - 1).."\"")
+ elseif align == "right" then
+ local pos = assert(ch_core.utf8_seek(value, 1, len - max))
+ table.insert(result, value:sub(pos, -1))
+ print("DEBUG: value \""..value.."\" align(right) max("..max..") => \""..value:sub(pos, -1).."\"")
+ else
+ local overflow = len - max
+ local half = math.floor(overflow / 2)
+ local pos1 = assert(ch_core.utf8_seek(value, 1, half))
+ local pos2 = (ch_core.utf8_seek(value, pos1, len - overflow) or 0) - 1
+ table.insert(result, value:sub(pos1, pos2))
+ print("DEBUG: value \""..value.."\" align(center) max("..max..") => \""..value:sub(pos1, pos2).."\"")
+ end
else
+ -- řetězec odpovídá
table.insert(result, value)
end
end
b = format:find("{", e + 1, true)
end
table.insert(result, format:sub(e + 1, -1))
+ print("DEBUG: result: "..dump2(result))
return table.concat(result)
end
+-- DEBUG:
+local dosadit_inner = dosadit
+dosadit = function(format, data, defaults)
+ local result = dosadit_inner(format, data, defaults)
+ print("DEBUG: dosadit(): "..dump2({format = format, data = data, defaults = defaults, result = result}))
+ return result
+end
+-- ------------------
+
local function sestavit_hlaseni(settings, settings_override, data, defaults)
local parts = {}
local function a(s)
@@ -216,7 +307,7 @@ local function sestavit_hlaseni(settings, settings_override, data, defaults)
local key = "tx_"..id
local result = settings_override[key] or settings[key]
if result == nil then
- local def = assert(hl_texty_id_to_idx[id])
+ local def = assert(hl_texty[hl_texty_id_to_idx[id]])
result = assert(def.default or def.sample)
end
return result
@@ -236,6 +327,7 @@ local function sestavit_hlaseni(settings, settings_override, data, defaults)
end
if data.VYCHOZI ~= nil then
a(t("zesm"))
+ a("{SEP}")
a(t("prijnk"))
else
a(t("prisnk"))
@@ -276,6 +368,7 @@ local function sestavit_hlaseni(settings, settings_override, data, defaults)
end
s = s:gsub("^{SEP}", "")
s = s:gsub("{SEP}$", "")
+ s = s:gsub("{SEP}", " ")
return s
end
@@ -292,15 +385,35 @@ local function get_or_add_anns(stn)
return anns
end
-local function get_ann_data(stn, epos, make_copy)
+local function init_ann_data(stn, epos)
local anns = get_or_add_anns(stn)
if anns == nil then
- return {}
+ return
end
- local ann = anns[epos]
- if ann == nil then
- return {}
+ local result = {
+ chat_dosah = 50,
+ fmt_cedule1 = "", fmt_cedule2 = "", fmt_cedule3 = "", fmt_cedule4 = "",
+ fmt_negdelay = "-{}",
+ fmt_prradek = {""},
+ fmt_radek = {""},
+ fn_firstupper = false,
+ fs_koleje = "",
+ koleje = "",
+ pos_cedule1_fs = "", pos_cedule2_fs = "", pos_cedule3_fs = "", pos_cedule4_fs = "",
+ pos_cedule1_pos = vector.zero(), pos_cedule2_pos = vector.zero(), pos_cedule3_pos = vector.zero(), pos_cedule4_pos = vector.zero(),
+ version = 1,
+ }
+ anns[epos] = result
+ return result
+end
+
+local function get_ann_data(stn, epos, make_copy)
+ local anns = get_or_add_anns(stn)
+ if anns == nil then
+ core.log("error", "get_ann_data() called on non-existent stn '"..tostring(stn).."'!")
+ return nil
end
+ local ann = assert(anns[epos] or init_ann_data(stn, epos))
if make_copy then
return table.copy(ann)
else
@@ -325,11 +438,90 @@ local function set_ann_data(stn, epos, data)
return true
end
+local function attach_sign(stn, epos, i, sign_pos)
+ -- zkontrolovat rozhlas:
+ local rozhl_pos = advtrains.decode_pos(epos)
+ core.load_area(rozhl_pos)
+ local rozhl_node = core.get_node(rozhl_pos)
+ if rozhl_node.name ~= rozhlas_node_name then
+ return false, "Staniční rozhlas se nenachází na očekávané pozici."
+ end
+ local rozhl_meta = core.get_meta(rozhl_pos)
+ if rozhl_meta:get_string("stn") ~= stn then
+ return false, "Staniční rozhlas přísluší k jiné dopravně." -- vnitřní chyba!
+ end
+ local data = get_ann_data(stn, epos)
+ if data == nil then
+ return false, "Data staničního rozhlasu nebyla nalezena."
+ end
+
+ -- zkontrolovat ceduli:
+ core.load_area(sign_pos)
+ local sign_node = core.get_node_or_nil(sign_pos)
+ if sign_node == nil or core.get_item_group(sign_node.name, "display_api") == 0 then
+ return false, "Toto není podporovaná cedule."
+ end
+
+ -- zkontrolovat vzdálenost:
+ if vector.distance(rozhl_pos, sign_pos) > 1024 then
+ return false, "Cedule je příliš daleko. Vzdálenost může být max. 1024 metrů."
+ end
+
+ -- zkontrolovat zadání:
+ if i < 1 or i > 4 then
+ return false, "Chybný index."
+ end
+
+ -- připojit:
+ local s = string.format("%d,%d,%d", sign_pos.x, sign_pos.y, sign_pos.z)
+ set_ann_data(stn, epos, {
+ ["pos_cedule"..i.."_fs"] = F(s),
+ ["pos_cedule"..i.."_pos"] = sign_pos,
+ })
+ return true, "Cedule úspěšně připojena ke staničnímu rozhlasu."
+end
+
+local function detach_sign(stn, epos, i)
+ -- zkontrolovat rozhlas:
+ local rozhl_pos = advtrains.decode_pos(epos)
+ core.load_area(rozhl_pos)
+ local rozhl_node = core.get_node(rozhl_pos)
+ if rozhl_node.name ~= rozhlas_node_name then
+ return false, "Staniční rozhlas se nenachází na očekávané pozici."
+ end
+ local rozhl_meta = core.get_meta(rozhl_pos)
+ if rozhl_meta:get_string("stn") ~= stn then
+ return false, "Staniční rozhlas přísluší k jiné dopravně." -- vnitřní chyba!
+ end
+ local data = get_ann_data(stn, epos)
+ if data == nil then
+ return false, "Data staničního rozhlasu nebyla nalezena."
+ end
+
+ -- zkontrolovat zadání:
+ if i < 1 or i > 4 then
+ return false, "Chybný index."
+ end
+
+ local key = "pos_cedule"..i.."_fs"
+ if data[key] == nil or data[key] == "" then
+ return false, "Cedule není připojena."
+ end
+
+ -- odpojit:
+ set_ann_data(stn, epos, {
+ [key.."_fs"] = "",
+ [key.."_pos"] = vector.zero(),
+ })
+ return true, "Cedule úspěšně odpojena."
+end
+
+
local function init_formspec_callback(custom_state, player, formname, fields)
local player_name = player:get_player_name()
local pos = custom_state.pos
local node = core.get_node(pos)
- if node.name ~= "advtrains_line_automation:stanicni_rozhlas" then
+ if node.name ~= rozhlas_node_name then
core.chat_send_player(player_name, "CHYBA: staniční rozhlas nenalezen!")
return
end
@@ -356,12 +548,7 @@ local function init_formspec_callback(custom_state, player, formname, fields)
meta:set_string("infotext", "staniční rozhlas ("..(stdata.name or "???")..")")
meta:set_string("owner", player_name)
meta:set_string("stn", stn)
- local anns = stdata.anns
- if anns == nil then
- anns = {}
- stdata.anns = anns
- end
- anns[custom_state.epos] = {}
+ init_ann_data(stn, custom_state.epos)
core.chat_send_player(player_name, "*** Úspěšně nastaveno.")
print("DEBUG: D")
end
@@ -370,7 +557,6 @@ end
local function get_setup_formspec(custom_state)
local player_name = assert(custom_state.player_name)
- local is_admin = assert(custom_state.is_admin)
local page = assert(custom_state.page)
local stations = assert(custom_state.stations)
local stn = custom_state.stn
@@ -381,11 +567,11 @@ local function get_setup_formspec(custom_state)
"size[15,16.5]"..
-- "style_type[textarea;font=mono]"..
"tabheader[0,0;0.75;tab;Nastavení 1,Nastavení 2,Import/export nastavení,Nápověda",
- ifthenelse(is_admin, ",Vlastnictví;", ";"),
+ ifthenelse(custom_state.is_admin, ",Vlastnictví;", ";"),
custom_state.page..";false;true]"..
"button_exit[14,0.25;0.75,0.75;close;X]"..
- "item_image[0.5,0.5;1,1;advtrains_line_automation:stanicni_rozhlas]"..
- "label[1.75,1;staniční rozhlas]"..
+ "item_image[0.5,0.5;1,1;"..rozhlas_node_name.."]"..
+ "label[1.75,1;staniční rozhlas (experimentální)]"..
"label[9,0.75;vlastník/ice:\n",
ch_core.prihlasovaci_na_zobrazovaci(custom_state.owner),
"]",
@@ -413,7 +599,7 @@ local function get_setup_formspec(custom_state)
"]container_end[]",
-- ----
"container[0.5,2.75]"..
- "label[0,0.25;Formátování na cedule ({1}, {2} atd.):]"..
+ "label[0,0.25;Formátování na cedule:]"..
"checkbox[5.5,0.25;fn_firstupper;první písmeno řádky vždy velké;",
ifthenelse(ifthenelse(custom_state.fn_firstupper ~= nil, custom_state.fn_firstupper, data.fn_firstupper), "true", "false"),
"]textarea[0,1;13.25,1.5;fmt_radek;formát řádků s odjezdem:;",
@@ -432,24 +618,28 @@ local function get_setup_formspec(custom_state)
"a poslední se použije i pro všechny následující.]"..
"container_end[]"..
"container[0.5,7.5]"..
- "label[0,0;formát záp. zpoždění (lze {}):]"..
-
- "field[0,0.25;3.25,0.75;fmt_negdelay;formát záp. zpoždění (lze {}):;",
- F(data.fmt_negdelay or "-{}"),
- "tooltip[fmt_negdelay;Formát v tomto poli se použije pro záporné zpoždění.\n"..
- "Značka {} se nahradí absolutní hodnotou záporného zpoždění.]"..
+ "field[0,0.25;3.25,0.75;fmt_nodelay;bez zpoždění;", F(data.fmt_nodelay or ""), "]"..
+ "field[4,0.25;3.25,0.75;fmt_delay;zpoždění ({} = číslo);", F(data.fmt_delay or "{}"), "]"..
+ "field[8,0.25;3.25,0.75;fmt_negdelay;záp.zpoždění ({} = číslo);", F(data.fmt_negdelay or "-{}"), "]"..
+ "tooltip[fmt_nodelay;Text pro značku {ZPOZDENI} v případě\\, že vlak jede bez zpoždění.]"..
+ "tooltip[fmt_delay;Formát pro značku {ZPOZDENI} v případě\\, že vlak má (kladné) zpoždění.\n"..
+ "Značka {} se nahradí počtem sekund zpoždění.]"..
+ "tooltip[fmt_negdelay;Formát pro značku {ZPOZDENI} v případě\\, že vlak má záporné zpoždění."..
+ "Značka {} se nahradí absolutní hodnotou počtu sekund záporného zpoždění.]"..
"textarea[0,1;13.25,2;;;",
- F("Značky, které můžete použít ve formátu řádků s odjezdem: {LINKA}, {VYCHOZI}, {CIL}, {KOLEJ}, {PRIJZA}, {ODJZA}, "..
- "{ZPOZDENI}, {PREDCH}, {NASL}, {JMVLAKU}, {TYP}, {TYPVLAKU}. "..
- "Příklady stanovení délky: {LINKA:4} (pevná délka), {LINKA:4-} (min. délka), {LINKA:-4} (max. délka), {LINKA:2-4} "..
- "(délka v rozmezí). Příklady náhradního textu: {LINKA|-}, {LINKA:3|-}. Zopakování symbolu (symbol nesmí být písmeno, "..
- "číslice, {, }, : ani |, lze použít i ve formátu prázdných řádků: {.:7}, { :4}.)"),
+ F("Podporované značky: {LINKA}, {VYCHOZI}, {CIL}, {KOLEJ}, {PRIJZA}, {ODJZA}, "..
+ "{ZPOZDENI}, {PREDCH}, {NASL}, {POLOHA}, {JMVLAKU}, {TYP}, {TYPVLAKU}.\n"..
+ "Formátovací specifikace: {LINKA:4} (pevná délka), {LINKA:4-} (min. délka), {LINKA:-4} (max. délka), {LINKA:2-4} "..
+ "(délka v rozmezí).\nNáhradní text: {LINKA|-}, {LINKA:3|není}.\nZopakování symbolu (symbol nesmí být písmeno, "..
+ "číslice, {, }, : ani |, symbol může být mezera, lze použít i ve formátu prázdných řádků: {.:7}, { :4}.)"),
"]container_end[]"..
"container[0.5,10.5]"..
- "box[0,0.15;14,0.05;#000000FF]"..
- "label[7,0.5;dosah hlášení v četu \\[m\\] (0=vyp):]"..
+ "box[0,0.15;14,0.05;#000000FF]"}
+ --[[
+ -- hlášení do četu (zatím neimplementováno):
+ a{ "label[7,0.5;dosah hlášení v četu \\[m\\] (0=vyp):]"..
"field[11.5,0.25;2,0.5;chat_dosah;;",
- tostring(custom_state.chat_dosah or data.chat_dosah or "50"),
+ tostring(data.chat_dosah or "50"),
"]"..
"tooltip[chat_dosah;Dosah je současně limitován doslechem jednotlivých hráčských postav.]"..
"label[0,0.5;texty pro hlášení příjezdu/přistavení vlaku v četu:]"..
@@ -459,7 +649,7 @@ local function get_setup_formspec(custom_state)
local id = "tx_"..def.id
a(def.fs_sample)
a(",")
- a(F(custom_state[id] or data[id] or def.default or def.sample))
+ a(F(data[id] or def.default or def.sample))
a(",")
end
formspec[#formspec] = ";"..(custom_state.tx_index or "").."]"
@@ -467,7 +657,7 @@ local function get_setup_formspec(custom_state)
if custom_state.tx_index ~= nil then
local def = assert(hl_texty[custom_state.tx_index])
local id = "tx_"..def.id
- local s = custom_state[id] or data[id]
+ local s = data[id]
if s ~= nil then
a(F(s))
else
@@ -491,7 +681,9 @@ local function get_setup_formspec(custom_state)
KOLEJ = "A",
})
a(F(hlaseni))
- a("]container_end[]"--[[..
+ a("]")
+ ]]
+ a("container_end[]"--[[..
-- ----
"container[0.5,9.25]"..
"label[0,0.25;Formáty řádků ({1}, {2} atd.):]"..
@@ -499,9 +691,43 @@ local function get_setup_formspec(custom_state)
)
a("button[0.5,15;14,1;btn_save;Uložit]")
elseif page == PAGE_SETUP_2 then
+ for i = 1, 4 do
+ local s = tostring(i)
+ local fs_pos_cedule = data["pos_cedule"..s.."_fs"] or ""
+ a{ "container[0.5,"..(2 * i - 2 + 6).."]"..
+ "textarea[0,0.5;13.25,1.5;fmt_cedule", s, ";cedule ", s, ":;",
+ CF(data["fmt_cedule"..s]),
+ "]field[2,0;4.5,0.5;pos_cedule", s, ";;",
+ fs_pos_cedule or "",
+ "]button[6.75,0;3,0.5;",
+ ifthenelse(fs_pos_cedule ~= "", "odp_cedule"..s..";odpojit", "pri_cedule"..s..";připojit"),
+ "]button_exit[10,0;3,0.5;zam_cedule", s, ";zaměřit...]"..
+ "container_end[]",
+ }
+ end
+ a{"label[0.5,14.5;", CF(custom_state.message),
+ "]button[0.5,15;14,1;btn_save;Uložit]"}
elseif page == PAGE_IMPORT then
+ a{
+ "textarea[0.5,2.5;14,10;nastaveni;nastavení ve formátu JSON:;",
+ -- CF(core.write_json(data, true)),
+ "(Zatím neimplementováno)",
+ "]label[0.5,13;",
+ CF(custom_state.message),
+ "]".. -- "button[0.5,13.5;14,1;importovat;importovat zadané nastavení a uložit]"..
+ "button_exit[0.5,15;14,1;close2;zavřít]",
+ }
+
elseif page == PAGE_HELP then
- elseif is_admin and page == PAGE_OWNERSHIP then
+ elseif custom_state.is_admin and page == PAGE_OWNERSHIP then
+ a{
+ "field[0.5,2.5;5,0.75;owner;vlastník/ice:;",
+ ch_core.prihlasovaci_na_zobrazovaci(custom_state.owner),
+ "]button[5.75,2.5;3,0.75;set_owner;nastavit]"..
+ "label[0.5,13;",
+ CF(custom_state.message),
+ "]button_exit[0.5,15;14,1;close2;zavřít]",
+ }
end
return table.concat(formspec)
end
@@ -509,6 +735,10 @@ end
local function setup_formspec_callback(custom_state, player, formname, fields)
print("DEBUG: setup_formspec_callback(): "..dump2({custom_state = custom_state, fields = fields, player_name = custom_state.player_name}))
assert(player:get_player_name() == custom_state.player_name)
+ local node = core.get_node(custom_state.pos)
+ if node.name ~= rozhlas_node_name then
+ return
+ end
local is_admin = custom_state.is_admin
local page = custom_state.page
local stn = custom_state.stn
@@ -540,9 +770,24 @@ local function setup_formspec_callback(custom_state, player, formname, fields)
table.insert(list, part)
end
end
- table.sort(list, function(a, b) return a < b end)
- data.koleje = set
- data.fs_koleje = F(table.concat(list, ","))
+ if #list == 0 then
+ -- všechny koleje
+ data.fs_koleje = ""
+ data.koleje = ""
+ elseif #list == 1 then
+ data.fs_koleje = F(list[1])
+ data.koleje = list[1]
+ else
+ table.sort(list, function(a, b) return a < b end)
+ data.fs_koleje = F(table.concat(list, ","))
+ data.koleje = set
+ end
+ end
+ if fields.fmt_delay then
+ data.fmt_delay = fields.fmt_delay
+ end
+ if fields.fmt_nodelay then
+ data.fmt_nodelay = fields.fmt_nodelay
end
if fields.fmt_negdelay then
data.fmt_negdelay = fields.fmt_negdelay
@@ -559,18 +804,39 @@ local function setup_formspec_callback(custom_state, player, formname, fields)
end
end
+ -- texty
+ if fields.texty then
+ local event = core.explode_table_event(fields.texty)
+ if (event.type == "CHG" or event.type == "DCL") and event.row ~= custom_state.tx_index and hl_texty[event.row] ~= nil then
+ custom_state.tx_index = event.row
+ end
+ end
+
+ if fields.preklad_set and custom_state.tx_index then
+ local def = assert(hl_texty[custom_state.tx_index])
+ custom_state.data["tx_"..def.id] = assert(fields.preklad)
+ return get_setup_formspec(custom_state)
+ end
+ if fields.chat_dosah and tonumber(fields.chat_dosah) ~= nil then
+ local new_dosah = tonumber(fields.chat_dosah)
+ if new_dosah ~= nil and new_dosah == math.floor(new_dosah) and new_dosah >= 0 and new_dosah < 1024 then
+ custom_state.data.chat_dosah = new_dosah
+ end
+ end
+
-- uložit?
if fields.btn_save then
local new_stn = custom_state.stations[custom_state.station_index].stn
if new_stn ~= stn then
-- přesunout rozhlas na jinou dopravnu
+ local meta = assert(core.get_meta(custom_state.pos))
local old_anns = get_or_add_anns(stn)
local new_anns = get_or_add_anns(new_stn)
if old_anns ~= nil and new_anns ~= nil then
local epos = custom_state.epos
new_anns[epos] = old_anns[epos]
old_anns[epos] = nil
- print("DEBUG: rozhlas moved from "..stn.." to "..new_stn)
+ meta:set_string("stn", new_stn)
stn = new_stn
custom_state.stn = new_stn
end
@@ -578,11 +844,82 @@ local function setup_formspec_callback(custom_state, player, formname, fields)
set_ann_data(stn, custom_state.epos, data)
end
elseif page == PAGE_SETUP_2 then
+ if fields.btn_save then
+ for i = 1, 4 do
+ data["fmt_cedule"..i] = assert(fields["fmt_cedule"..i])
+ end
+ set_ann_data(stn, custom_state.epos, data)
+ return get_setup_formspec(custom_state)
+ else
+ for i = 1, 4 do
+ if fields["pri_cedule"..i] then
+ -- připojit ceduli:
+ local pos_cedule_str = fields["pos_cedule"..i]
+ local x, y, z = pos_cedule_str:match("^(-?%d+),(-?%d+),(-?%d+)$")
+ if x == nil or y == nil or z == nil then
+ custom_state.message = "Chybný formát pozice: "..pos_cedule_str
+ return get_setup_formspec(custom_state)
+ end
+ local pos_cedule = vector.new(tonumber(x), tonumber(y), tonumber(z))
+ local success, message = attach_sign(stn, custom_state.epos, i, pos_cedule)
+ if success then
+ local current_data = get_ann_data(stn, custom_state.epos)
+ if current_data ~= nil then
+ custom_state.data = current_data
+ end
+ custom_state.message = "Cedule úspěšně připojena."
+ else
+ custom_state.message = "CHYBA: "..message
+ end
+ return get_setup_formspec(custom_state)
+ end
+ if fields["odp_cedule"..i] then
+ local success, message = detach_sign(stn, custom_state.epos, i)
+ if success then
+ local current_data = get_ann_data(stn, custom_state.epos)
+ if current_data ~= nil then
+ custom_state.data = current_data
+ end
+ custom_state.message = "Cedule úspěšně odpojena."
+ else
+ custom_state.message = "CHYBA: "..message
+ end
+ return get_setup_formspec(custom_state)
+ end
+ if fields["zam_cedule"..i] then
+ local player_name = player:get_player_name()
+ local stack = player:get_wielded_item()
+ if stack:is_empty() then
+ player:set_wielded_item("advtrains_line_automation:sign_selector")
+ core.chat_send_player(player_name, "*** Levým klikem vyberte ceduli k připojení...")
+ else
+ player:get_inventory():add_item("main", "advtrains_line_automation:sign_selector")
+ core.chat_send_player(player_name, "*** Levým klikem výběrovým nástrojem vyberte ceduli k připojení...")
+ end
+ punch_context[player_name] = {stn = assert(custom_state.stn), epos = custom_state.epos, i = i}
+ return
+ end
+ end
+ end
elseif page == PAGE_IMPORT then
+ if fields.importovat then
+ local s = assert(fields.nastaveni)
+ -- TODO
+ end
elseif page == PAGE_HELP then
+ -- nic
elseif page == PAGE_OWNERSHIP then
- if is_admin then
- -- TODO
+ if is_admin and fields.set_owner then
+ local new_owner = ch_core.jmeno_na_existujici_prihlasovaci(fields.owner or "")
+ if new_owner == nil then
+ custom_state.message = "Postava '"..(fields.owner or "").."' neexistuje!"
+ else
+ core.load_area(custom_state.pos)
+ local meta = core.get_meta(custom_state.pos)
+ meta:set_string("owner", new_owner)
+ custom_state.owner = new_owner
+ end
+ return get_setup_formspec(custom_state)
end
end
if fields.tab then
@@ -593,6 +930,7 @@ local function setup_formspec_callback(custom_state, player, formname, fields)
(is_admin and new_tab == PAGE_OWNERSHIP)
) then
custom_state.page = new_tab
+ custom_state.message = "" -- smazat zprávu
end
return get_setup_formspec(custom_state)
end
@@ -601,6 +939,229 @@ local function setup_formspec_callback(custom_state, player, formname, fields)
end
end
+local debug_counter = 0
+
+local function update_ann(stn, epos, signs, deps, rwtime)
+ print("DEBUG: update_ann(): "..dump2({stn = stn, epos = epos, signs = signs, deps = deps, rwtime = rwtime}))
+ local ann = get_ann_data(stn, epos)
+ if ann == nil then
+ core.log("error", "update_ann() called for "..stn.."/"..epos..", but ann is nil!")
+ return
+ end
+ local tracks = ann.koleje
+ if tracks ~= nil and type(tracks) ~= "table" then
+ if tracks == "" then
+ tracks = nil
+ else
+ tracks = {[tracks] = true}
+ end
+ end
+ -- print("DEBUG: "..dump2({tracks = tracks}))
+ local lines = {}
+ -- update_ann(assert(stn), assert(ann.rozh_epos), signs, deps)
+ for _, dep in ipairs(deps) do
+ if (tracks == nil or tracks[dep.track]) and (dep.dep == nil or dep.dep > rwtime) then
+ local linevar_def = dep.linevar_def
+ local stops = linevar_def.stops
+ local line = {}
+ line.LINKA = linevar_def.line or ""
+ line.VYCHOZI = al.get_line_description(linevar_def, {line_number = false, first_stop = true, last_stop = false})
+ line.CIL = dep.destination
+ print("DEBUG: CIL = '"..line.CIL.."'")
+ if dep.track ~= "" then
+ line.KOLEJ = dep.track
+ end
+ if dep.arr ~= nil then
+ line.PRIJZA = math.ceil((dep.arr - rwtime) / 5) * 5
+ end
+ if dep.dep ~= nil then
+ line.ODJZA = math.ceil((dep.dep - rwtime) / 5) * 5
+ end
+ local abs_delay = math.abs(dep.delay)
+ if abs_delay < 5 then
+ line.ZPOZDENI = ann.fmt_nodelay or ""
+ else
+ line.ZPOZDENI = dosadit(
+ ifthenelse(dep.delay > 0, ann.fmt_delay or "{}", ann.fmt_negdelay or "-{}"),
+ {[""] = tostring(5 * math.ceil(abs_delay / 5))}
+ )
+ end
+ -- PREDCH
+ if dep.prev_stop ~= nil then
+ line.PREDCH = dep.prev_stop
+ end
+ -- NASL
+ if dep.next_stop ~= nil then
+ line.NASL = dep.next_stop
+ end
+ -- POLOHA
+ if dep.last_pos ~= nil then
+ line.POLOHA = dep.last_pos
+ end
+ -- JMVLAKU
+ if linevar_def.train_name ~= nil then
+ line.JMVLAKU = linevar_def.train_name
+ end
+ -- TYP
+ line.TYP = "Os"
+ -- TYPVLAKU
+ line.TYPVLAKU = "osobní vlak"
+ debug_counter = debug_counter + 1
+ line.POCITADLO = tostring(debug_counter)
+ -- print("DEBUG: line filled: "..dump2({line = line}))
+ table.insert(lines, line)
+ end
+ end
+ local full_fmt, empty_fmt = ann.fmt_radek[1] or "", ann.fmt_prradek[1] or ""
+ local formatted_lines = {}
+ for i = 1, 9 do
+ if i > 1 then
+ if ann.fmt_radek[i] ~= nil then
+ full_fmt = ann.fmt_radek[i]
+ end
+ if ann.fmt_prradek[i] ~= nil then
+ empty_fmt = ann.fmt_prradek[i]
+ end
+ end
+ local s
+ if lines[i] ~= nil then
+ s = dosadit(full_fmt, lines[i])
+ else
+ s = dosadit(empty_fmt, {})
+ end
+ if s ~= "" and ann.fn_firstupper then
+ local l = ch_core.utf8_seek(s, 1, 1)
+ if l == nil then
+ s = ch_core.na_velka_pismena(s)
+ else
+ local c = s:sub(1, l - 1)
+ local uc = ch_core.na_velka_pismena(c)
+ if uc ~= c then
+ s = uc..s:sub(l, -1)
+ end
+ end
+ end
+ formatted_lines[tostring(i)] = s
+ end
+ --[[print("DEBUG: formatted lines: "..dump2({formatted_lines = formatted_lines, fmt_radek = ann.fmt_radek, fmt_prradek = ann.fmt_prradek,
+ full_fmt = full_fmt, empty_fmt = empty_fmt}))]]
+ if signs ~= nil then
+ for i = 1, 4 do
+ local sign_pos = signs[i]
+ if sign_pos ~= nil and core.compare_block_status(sign_pos, "active") then
+ local s = dosadit(ann["fmt_cedule"..i] or "", formatted_lines)
+ if has_signs_api then
+ signs_api.set_display_text(sign_pos, s)
+ end
+ end
+ end
+ end
+end
+
+local globalstep_time = -5
+
+local function globalstep(dtime)
+ globalstep_time = globalstep_time + dtime
+ if globalstep_time < 0 then
+ return
+ end
+ print("DEBUG: globalstep...")
+ globalstep_time = globalstep_time - 5
+
+ local rwtime = rwt.to_secs(rwt.get_time())
+ -- Shromáždit rozhlasy:
+ local subscriptions = {--[[
+ [stn] = {{
+ rozh_pos = vector,
+ rozh_epos = string,
+ rozh_def = table,
+ signs = {[1..4] = vector or nil} or nil,
+ }...}
+ ]]}
+ local signs = {}
+ for stn, stdata in pairs(advtrains.lines.stations) do
+ local anns = stdata.anns
+ if stdata.anns ~= nil then
+ for rozh_epos, ann in pairs(stdata.anns) do
+ local rozh_pos = advtrains.decode_pos(rozh_epos)
+ local signs_count = 0
+ for i = 1, 4 do
+ local s = ann["pos_cedule"..i.."_fs"]
+ if s ~= nil and s ~= "" then
+ local sign_pos = assert(ann["pos_cedule"..i.."_pos"])
+ if core.compare_block_status(sign_pos, "active") then
+ signs[i] = sign_pos
+ signs_count = signs_count + 1
+ end
+ end
+ end
+ if signs_count > 0 then
+ -- nějaké cedule jsou aktivní
+ -- print("DEBUG: - "..rozh_epos.." : added ("..stn.."), because has "..signs_count.." active signs")
+ table.insert(goa(subscriptions, stn), {rozh_pos = rozh_pos, rozh_epos = rozh_epos, rozh_def = ann, signs = signs})
+ signs = {}
+ elseif core.compare_block_status(rozh_pos, "active") then
+ -- cedule nejsou aktivní, ale rozhlas ano
+ print("DEBUG: - "..rozh_epos.." : added ("..stn.."), because is active")
+ table.insert(goa(subscriptions, stn), {rozh_pos = rozh_pos, rozh_epos = rozh_epos, rozh_def = ann})
+ end
+ end
+ else
+ -- print("DEBUG: - "..stn.." not added (anns: "..ifthenelse(stdata.anns == nil, "nil", "non-nil")..")")
+ end
+ end
+
+ -- Shromáždit vlaky:
+ local deps_by_stn = {}
+ for stn, _ in pairs(subscriptions) do
+ deps_by_stn[stn] = {}
+ end
+ for _, train in pairs(advtrains.trains) do
+ local ls, linevar_def = al.get_line_status(train)
+ if linevar_def ~= nil then
+ local prediction = al.predict_train(ls, linevar_def, rwtime)
+ local last_pos = al.get_last_pos_station_name(ls)
+ local destination = "???"
+ for i = #prediction, 1, -1 do
+ local p = prediction[i]
+ if not p.hidden then
+ destination = al.get_station_name(p.stn)
+ break
+ end
+ end
+ for _, record in ipairs(prediction) do
+ local deps = deps_by_stn[record.stn]
+ if deps ~= nil and record.dep ~= nil then
+ local record_index = assert(record.index)
+ local other_index, other_data = al.get_prev_stop(linevar_def, record_index, false)
+ if other_index ~= nil then
+ record.prev_stop = al.get_station_name(other_data.stn)
+ end
+ other_index, other_data = al.get_next_stop(linevar_def, record_index, false)
+ if other_index ~= nil then
+ record.next_stop = al.get_station_name(other_data.stn)
+ end
+ record.last_pos = last_pos -- název poslední dopravny, kde byl vlak spatřen
+ record.linevar = linevar_def.name
+ record.linevar_def = linevar_def
+ record.destination = destination
+ table.insert(deps, record)
+ end
+ end
+ end
+ end
+
+ -- Aktualizovat rozhlasy:
+ for stn, deps in pairs(deps_by_stn) do
+ table.sort(deps, function(a, b) return assert(a.dep) < assert(b.dep) end)
+ for _, ann in ipairs(subscriptions[stn]) do
+ update_ann(assert(stn), assert(ann.rozh_epos), ann.signs, deps, rwtime)
+ end
+ end
+end
+
+core.register_globalstep(globalstep)
+
local function can_dig(pos, player)
if player ~= nil and core.is_player(player) then
local owner = core.get_meta(pos):get_string("owner")
@@ -629,7 +1190,12 @@ end
local function on_dig(pos, node, digger)
-- TODO?
- return core.node_dig(pos, node, digger)
+ -- return core.node_dig(pos, node, digger)
+ if has_unifieddyes then
+ return unifieddyes.on_dig(pos, node, digger)
+ else
+ return core.node_dig(pos, node, digger)
+ end
end
local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
@@ -675,7 +1241,7 @@ local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
"formspec_version[6]"..
"size[15,8]"..
"button_exit[14,0.25;0.75,0.75;close;X]"..
- "item_image[0.5,0.5;1,1;advtrains_line_automation:stanicni_rozhlas]"..
+ "item_image[0.5,0.5;1,1;"..rozhlas_node_name.."]"..
"label[1.75,1;staniční rozhlas]"..
"label[0.5,2.25;vyberte dopravnu:]"..
"button_exit[0.5,6.75;14,1;zvolit_dopravnu;Zvolit]"..
@@ -688,6 +1254,7 @@ local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
table.insert(formspec, F(candidate.stn.." | "..candidate.name.." ("..candidate.distance.." m)"))
end
+ custom_state.selection_index = 1
table.insert(formspec, ";1]")
else
table.insert(formspec, ";]")
@@ -703,6 +1270,7 @@ local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
local stdata = advtrains.lines.stations[stn]
if stdata == nil or stdata.anns == nil or stdata.anns[epos] == nil then
core.chat_send_player(player_name, "CHYBA: data dopravny nenalezena!")
+ print("DEBUG: stn = <"..stn..">")
return
end
local stations = advtrains.lines.load_stations_for_formspec()
@@ -734,16 +1302,62 @@ local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
setup_formspec_callback, custom_state, {})
end
+local function selector_on_use(itemstack, user, pointed_thing)
+ if pointed_thing.type ~= "node" then
+ return
+ end
+ if user ~= nil then
+ local player_name = user:get_player_name()
+ local pc = punch_context[player_name]
+ if pc ~= nil then
+ local success, message = attach_sign(assert(pc.stn), assert(pc.epos), assert(pc.i), assert(pointed_thing.under))
+ if not success then
+ message = message.." Zaměřování bude zrušeno."
+ end
+ core.chat_send_player(player_name, message)
+ end
+ end
+ return ItemStack()
+end
+
+local box = {
+ type = "fixed",
+ fixed = {
+ {-0.25, -0.25, 0, 0.25, 0.25, 0.5},
+ {-0.5, -0.4, -0.25, 0.5, 0.4, 0},
+ },
+}
+
def = {
- description = "staniční rozhlas",
- tiles = {{name = "blank.png^[noalpha"}}, -- TODO
- drawtype = "normal",
+ description = "staniční rozhlas [EXPERIMENTÁLNÍ]",
+ tiles = {{name = "default_steel_block.png", backface_culling = true}},
+ drawtype = "mesh",
+ mesh = "advtrains_tuber.obj",
paramtype = "light",
- paramtype2 = "facedir", -- TODO: => colorfacedir
+ paramtype2 = "4dir",
+ selection_box = box,
+ collision_box = box,
+ groups = {oddly_breakable_by_hand = 3, ud_param2_colorable = 1, experimental = 1}, -- TODO
+ sounds = default.node_sound_metal_defaults(),
can_dig = can_dig,
on_dig = on_dig,
on_construct = on_construct,
on_destruct = on_destruct,
on_rightclick = on_rightclick,
}
-core.register_node("advtrains_line_automation:stanicni_rozhlas", def)
+if has_unifieddyes then
+ def.paramtype2 = "color4dir"
+ def.palette = "unifieddyes_palette_color4dir.png"
+end
+core.register_node(rozhlas_node_name, def)
+
+def = {
+ description = "levým klikem zvolte ceduli pro připojení",
+ groups = {not_in_creative_inventory = 1, tool = 1},
+ inventory_image = "[combine:16x16:7,0=blank.png\\^[noalpha\\^[resize\\:2x16:0,7=blank.png\\^[noalpha\\^[resize\\:16x2",
+ wield_image = "blank.png",
+ on_use = selector_on_use,
+}
+
+core.register_tool("advtrains_line_automation:sign_selector", def)
+
diff --git a/advtrains_line_automation/structs.md b/advtrains_line_automation/structs.md
index 9b8d27d..cffb940 100644
--- a/advtrains_line_automation/structs.md
+++ b/advtrains_line_automation/structs.md
@@ -102,7 +102,44 @@ station = {
},
anns = { -- staniční rozhlasy
[encoded_pos] = {
- ...
+ -- dosah zpráv v četu (>= 0, nil znamená 50):
+ chat_dosah = int or nil,
+
+ -- formát jednotlivých cedulí, může používat značky {1} až {9} a může mít víc řádků
+ fmt_cedule[1234] = string or nil,
+
+ -- formát pro záporné zpoždění; nil znamená "-{}"
+ fmt_negdelay = string or nil,
+
+ -- pole formátů pro prázdné řádky (vždy obsahuje alespoň prvek [1])
+ fmt_prradek = {string...} or nil,
+
+ -- pole formátů pro řádky s odjezdy (vždy obsahuje alespoň prvek [1])
+ fmt_radek = {string...} or nil,
+
+ -- udává, zda na cedulích bude první znak každého řádku převeden na velké písmeno:
+ fn_firstupper = bool,
+
+ -- obsah pole "koleje" zformátovaný pro použití ve formspecu; prázdný řetězec "" znamená, že st. rozhlas platí pro všechny koleje
+ -- a na .koleje pak nezáleží
+ fs_koleje = string or nil,
+
+ -- pokud st. rozhlas není omezený na určité koleje, nil nebo ""
+ -- je-li omezen na jednu konkrétní kolej, pak jde o název této koleje
+ -- je-li omezen na více kolejí, pak jde o množinu indexovanou označeními kolejí
+ koleje = {[string] = true, ...} or string or nil,
+
+ -- pozice připojených cedulí ve tvaru pro použití ve formspecu, nebo "", pokud daná cedule není připojená
+ pos_cedule[1234]_fs = string or nil,
+
+ -- pozice připojených cedulí ve formě vektoru
+ pos_cedule[1234]_pos = vector or nil,
+
+ -- číslo verze systému staničního rozhlasu (pro detekci zastaralých rozhlasů)
+ version = int,
+
+ -- řetězce pro formátování hlášení v četu; nemusí být uvedeny všechny, nil znamená použít výchozí text
+ tx_* = string or nil,
}
}
}