aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSingularis <singularis@volny.cz>2025-01-19 06:52:20 +0100
committerorwell <orwell@bleipb.de>2025-05-27 20:22:01 +0200
commit8965b1115473346df8aa80bc2c3d61eab3509d62 (patch)
treedeabca1e71cd6774b02a69b372514b1b802c41b5
parent4ad37ae721a9db5754ce0489dc68ad66e6fad9b6 (diff)
downloadadvtrains-8965b1115473346df8aa80bc2c3d61eab3509d62.tar.gz
advtrains-8965b1115473346df8aa80bc2c3d61eab3509d62.tar.bz2
advtrains-8965b1115473346df8aa80bc2c3d61eab3509d62.zip
[advtrains_line_automation] vývoj staničního rozhlasu
- [advtrains_interlocking] logování zapnutí/vypnutí ARS - [advtrains_line_automation] opět zapnuto logování linkových odjezdů/příjezdů - [moretrees] švestky jsou nově jedlé
-rw-r--r--advtrains_interlocking/tcb_ts_ui.lua2
-rw-r--r--advtrains_line_automation/init.lua1
-rw-r--r--advtrains_line_automation/line_functions.lua6
-rw-r--r--advtrains_line_automation/station_announcement.lua749
-rw-r--r--advtrains_line_automation/structs.md5
5 files changed, 760 insertions, 3 deletions
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index 19e0666..263a1f0 100644
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -808,9 +808,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if tcbs.ars_disabled and fields.arsenable then
+ core.log("action", pname.." turn ARS on at "..pts)
tcbs.ars_disabled = nil
end
if not tcbs.ars_disabled and fields.arsdisable then
+ core.log("action", pname.." turn ARS off at "..pts)
tcbs.ars_disabled = true
end
diff --git a/advtrains_line_automation/init.lua b/advtrains_line_automation/init.lua
index 7e65174..2d4a97e 100644
--- a/advtrains_line_automation/init.lua
+++ b/advtrains_line_automation/init.lua
@@ -24,6 +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")
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 168c1e7..0a4e6d2 100644
--- a/advtrains_line_automation/line_functions.lua
+++ b/advtrains_line_automation/line_functions.lua
@@ -711,7 +711,7 @@ function al.on_train_enter(pos, train_id, train, index)
else
-- koncová zastávka
can_start_line = stop_def.mode == MODE_FINAL_CONTINUE
- -- core.log("action", "Train "..train_id.." arrived at the final station "..stop_def.stn.." of linevar "..ls.linevar.." after "..(rwtime - ls.linevar_dep).." seconds.")
+ core.log("action", "Train "..train_id.." arrived at the final station "..stop_def.stn.." of linevar "..ls.linevar.." after "..(rwtime - ls.linevar_dep).." seconds.")
debug_print("Vlak "..train_id.." skončil jízdu na lince "..ls.linevar..", může pokračovat na jinou linku: "..(can_start_line and "ihned" or "na příští zastávce"))
train.text_inside = al.get_stop_description(linevar_def.stops[next_index])
local current_passage = current_passages[train_id]
@@ -751,9 +751,9 @@ function al.on_train_enter(pos, train_id, train, index)
update_value(train, "routingcode", new_routingcode)
-- začít novou linku?
- if can_start_line and line_start(train, stn, planned_departure) then
+ if can_start_line and stn ~= nil and stn ~= "" and line_start(train, stn, planned_departure) then
debug_print("Vlak "..train_id.." zahájil jízdu na nové lince ("..ls.linevar..") ze stanice "..stn..".")
- -- core.log("action", "Train "..train_id.." started a route with linevar '"..ls.linevar.."' at station '"..stn.."'.")
+ core.log("action", "Train "..train_id.." started a route with linevar '"..ls.linevar.."' at station '"..stn.."'.")
train.text_inside = get_station_name(stn)
assert(ls.linevar)
linevar_def = assert(al.try_get_linevar_def(ls.linevar))
diff --git a/advtrains_line_automation/station_announcement.lua b/advtrains_line_automation/station_announcement.lua
new file mode 100644
index 0000000..c20fa3c
--- /dev/null
+++ b/advtrains_line_automation/station_announcement.lua
@@ -0,0 +1,749 @@
+local def
+local F = core.formspec_escape
+local ifthenelse = assert(ch_core.ifthenelse)
+
+local PAGE_SETUP_1 = 1
+local PAGE_SETUP_2 = 2
+local PAGE_IMPORT = 3
+local PAGE_HELP = 4
+local PAGE_OWNERSHIP = 5
+
+local hl_texty = {
+ {
+ id = "vcpp",
+ sample = "Vážení cestující, prosíme pozor!",
+ default = "",
+ }, {
+ id = "tvl",
+ sample = "{TYPVLAKU}",
+ }, {
+ id = "vlk",
+ sample = "Vlak",
+ }, {
+ id = "lnky",
+ sample = "linky {LINKA}",
+ }, {
+ id = "jmvlku",
+ sample = "{JMVLAKU}",
+ }, {
+ id = "zesm",
+ sample = "ze směru {VYCHOZI}",
+ }, {
+ id = "prijnk",
+ sample = "přijíždí na kolej {KOLEJ}.",
+ }, {
+ id = "prisnk",
+ sample = "bude přistaven na kolej {KOLEJ}.",
+ }, {
+ id = "zpoz",
+ sample = "Vlak má {ZPOZDENI} sekund zpoždění.",
+ default = "",
+ }, {
+ id = "zpozz",
+ sample = "Vlak má -{ZPOZDENI} sekund zpoždění.",
+ default = "",
+ }, {
+ id = "vkonc",
+ sample = "Vlak zde jízdu končí.",
+ }, {
+ id = "pokrnc",
+ sample = "Vlak dále pokračuje směr {NASL} a {CIL}",
+ }, {
+ id = "pokrc",
+ sample = "Vlak pokračuje směr {CIL}",
+ }, {
+ id = "ozasek",
+ sample = ", odjezd za {ODJZA} sekund.",
+ }, {
+ id = "dek",
+ sample = "Děkujeme, že používáte naše služby.",
+ default = "",
+ }
+}
+local hl_texty_id_to_idx = function()
+ local result = {}
+ for i, def in ipairs(hl_texty) do
+ local id = assert(def.id)
+ if result[id] ~= nil then
+ error("Duplicity: id = "..id.."!")
+ end
+ def.fs_sample = F(def.sample)
+ def.fs_default = F(def.default or def.sample)
+ result[id] = i
+ end
+ return result
+end
+hl_texty_id_to_idx = hl_texty_id_to_idx()
+
+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
+
+--[[
+ Vrací:
+ - success = bool
+ - min = int or nil (pro success == false vždy nil)
+ - max = int or nil (pro success == false vždy nil)
+]]
+local function lengths_from_string(s)
+ if s == "" or s == "-" then
+ return true, nil, nil
+ 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
+ end
+ local min, max = s:match("^(%d*)-(%d*)$")
+ if min == nil then
+ return false, nil, nil -- bad format
+ end
+ min, max = tonumber(min), tonumber(max)
+ if min ~= nil and min > 256 then min = 256 end
+ if max ~= nil and max > 256 then max = 256 end
+ if min ~= nil and max ~= nil and min > max then
+ min = max
+ end
+ return true, min, max
+end
+
+local function lengths_to_string(min, max)
+ if min == nil then
+ if max ~= nil then
+ return "-"..max
+ else
+ return ""
+ end
+ elseif max == nil then
+ return min.."-"
+ elseif min == max then
+ return tostring(min)
+ else
+ return min.."-"..max
+ end
+end
+
+local alphanum_chars_set = {
+ ["a"] = true, ["A"] = true, ["á"] = true, ["Á"] = true, ["ä"] = true, ["Ä"] = true, ["b"] = true, ["B"] = true, ["č"] = true,
+ ["Č"] = true, ["d"] = true, ["D"] = true, ["ď"] = true, ["Ď"] = true, ["e"] = true, ["E"] = true, ["é"] = true, ["É"] = true,
+ ["ě"] = true, ["Ě"] = true, ["f"] = true, ["F"] = true, ["g"] = true, ["G"] = true, ["h"] = true, ["H"] = true, ["i"] = true,
+ ["I"] = true, ["í"] = true, ["Í"] = true, ["j"] = true, ["J"] = true, ["k"] = true, ["K"] = true, ["l"] = true, ["L"] = true,
+ ["ĺ"] = true, ["Ĺ"] = true, ["ľ"] = true, ["Ľ"] = true, ["m"] = true, ["M"] = true, ["n"] = true, ["N"] = true, ["ň"] = true,
+ ["Ň"] = true, ["o"] = true, ["O"] = true, ["ó"] = true, ["Ó"] = true, ["ô"] = true, ["Ô"] = true, ["p"] = true, ["P"] = true,
+ ["q"] = true, ["Q"] = true, ["r"] = true, ["R"] = true, ["ŕ"] = true, ["Ŕ"] = true, ["ř"] = true, ["Ř"] = true, ["s"] = true,
+ ["S"] = true, ["š"] = true, ["Š"] = true, ["t"] = true, ["T"] = true, ["ť"] = true, ["Ť"] = true, ["u"] = true, ["U"] = true,
+ ["ú"] = true, ["Ú"] = true, ["ů"] = true, ["Ů"] = true, ["v"] = true, ["V"] = true, ["w"] = true, ["W"] = true, ["x"] = true,
+ ["X"] = true, ["y"] = true, ["Y"] = true, ["ý"] = true, ["Ý"] = true, ["z"] = true, ["Z"] = true, ["ž"] = true, ["Ž"] = true,
+ ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true, ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true,
+ ["9"] = true,
+}
+
+local function dosadit(format, data, defaults)
+ assert(type(format) == "string")
+ assert(type(data) == "table")
+ if defaults == nil then
+ defaults = {}
+ end
+ local result = {}
+ local i = 1
+ local e = 0
+ local b = format:find("{", e + 1, true)
+ while b ~= nil do
+ if e < b - 1 then
+ table.insert(result, format:sub(e + 1, b - 1))
+ end
+ e = format:find("}", b + 1, true)
+ if e == nil then
+ core.log("warning", "[advtrains_line_automation] dosadit(): invalid format: <"..format..">")
+ table.insert(result, format:sub(b, -1))
+ break
+ end
+ local tag = format:sub(b + 1, e - 1)
+ 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)
+ end
+ local min, max
+ if tagfmt ~= "" then
+ local success
+ success, min, max = lengths_from_string(tagfmt)
+ end
+ 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
+ table.insert(result, string.rep(tag, min))
+ else
+ table.insert(result, tag)
+ end
+ else
+ 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))
+ elseif max ~= nil and len > max then
+ table.insert(result, ch_core.utf8_truncate_right(value, max))
+ else
+ table.insert(result, value)
+ end
+ end
+ b = format:find("{", e + 1, true)
+ end
+ table.insert(result, format:sub(e + 1, -1))
+ return table.concat(result)
+end
+
+local function sestavit_hlaseni(settings, settings_override, data, defaults)
+ local parts = {}
+ local function a(s)
+ table.insert(parts, s)
+ end
+ local function t(id)
+ if id == nil then
+ return ""
+ end
+ 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])
+ result = assert(def.default or def.sample)
+ end
+ return result
+ end
+ assert(settings)
+ if settings_override == nil then
+ settings_override = {}
+ end
+ assert(data)
+ a(t("vcpp"))
+ a("{SEP}")
+ a(t(ifthenelse(data.TYPVLAKU ~= nil, "tvl", "vlk")))
+ a("{SEP}")
+ if data.LINKA ~= nil then
+ a(t("lnky"))
+ a("{SEP}")
+ end
+ if data.VYCHOZI ~= nil then
+ a(t("zesm"))
+ a(t("prijnk"))
+ else
+ a(t("prisnk"))
+ end
+ a("{SEP}")
+ if data.typ_zpozdeni == "+" then
+ a(t("zpoz"))
+ a("{SEP}")
+ elseif data.typ_zpozdeni == "-" then
+ a(t("zpozz"))
+ a("{SEP}")
+ end
+ if not data.CIL then
+ a(t("vkonc"))
+ elseif data.NASL then
+ a(t("pokrnc"))
+ else
+ a(t("pokrc"))
+ end
+ if data.ODJZA then
+ a(t("ozasek"))
+ else
+ a(".")
+ end
+ a("{SEP}")
+ a(t("dek"))
+ data = table.copy(data)
+ data.SEP = "{SEP}"
+ local s = table.concat(parts)
+ s = assert(dosadit(s, data, defaults))
+ s = s:gsub(" *{SEP} *", "{SEP}")
+ while true do
+ t = s:gsub("{SEP}{SEP}", "{SEP}")
+ if t:len() == s:len() then
+ break
+ end
+ s = t
+ end
+ s = s:gsub("^{SEP}", "")
+ s = s:gsub("{SEP}$", "")
+ return s
+end
+
+local function get_or_add_anns(stn)
+ local station = advtrains.lines.stations[stn]
+ if station == nil then
+ return nil -- dopravna neexistuje!
+ end
+ local anns = station.anns
+ if anns == nil then
+ anns = {}
+ station.anns = anns
+ end
+ return anns
+end
+
+local function get_ann_data(stn, epos, make_copy)
+ local anns = get_or_add_anns(stn)
+ if anns == nil then
+ return {}
+ end
+ local ann = anns[epos]
+ if ann == nil then
+ return {}
+ end
+ if make_copy then
+ return table.copy(ann)
+ else
+ return ann
+ end
+end
+
+local function set_ann_data(stn, epos, data)
+ local anns = get_or_add_anns(stn)
+ if anns == nil then
+ return false
+ end
+ local ann = anns[epos]
+ if ann ~= nil then
+ for k, v in pairs(data) do
+ ann[k] = v
+ end
+ else
+ anns[epos] = table.copy(data)
+ end
+ print("DEBUG: set_ann_data() => "..dump2({stn = stn, epos = epos, ann = anns[epos]}))
+ return true
+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
+ core.chat_send_player(player_name, "CHYBA: staniční rozhlas nenalezen!")
+ return
+ end
+ if not core.check_player_privs(player, "railway_operator") then
+ core.chat_send_player(player_name, "*** K instalaci staničního rozhlasu je nutné právo railway_operator!")
+ return
+ end
+ if fields.dopravna then
+ local event = core.explode_textlist_event(fields.dopravna)
+ local new_index = tonumber(event.index)
+ if new_index ~= nil and custom_state.list[new_index] ~= nil then
+ custom_state.selection_index = new_index
+ end
+ if event.type == "DCL" then
+ fields.zvolit_dopravnu = "true"
+ end
+ end
+ if fields.zvolit_dopravnu and custom_state.selection_index ~= nil then
+ local stn = assert(custom_state.list[custom_state.selection_index].stn)
+ local stdata = advtrains.lines.stations[stn]
+ if stdata ~= nil then
+ print("DEBUG: C")
+ local meta = core.get_meta(pos)
+ 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] = {}
+ core.chat_send_player(player_name, "*** Úspěšně nastaveno.")
+ print("DEBUG: D")
+ end
+ end
+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
+ local data = custom_state.data
+
+ local formspec = {
+ "formspec_version[6]"..
+ "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í;", ";"),
+ 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]"..
+ "label[9,0.75;vlastník/ice:\n",
+ ch_core.prihlasovaci_na_zobrazovaci(custom_state.owner),
+ "]",
+ }
+ local function a(x)
+ if type(x) == "table" then
+ for _, s in ipairs(x) do
+ table.insert(formspec, s)
+ end
+ else
+ table.insert(formspec, x)
+ end
+ end
+ if page == PAGE_SETUP_1 then
+ a( "container[0.5,1.5]"..
+ "label[0,0.5;dopravna:]"..
+ "dropdown[1.75,0.2;5,0.6;dopravna;")
+ for i, station in ipairs(stations) do
+ a(ifthenelse(i ~= 1, ",", "")..F(station.stn).." | "..F(station.name))
+ end
+ a{";"..custom_state.station_index..";true]"..
+ "label[7,0.5;omezit jen na koleje:]"..
+ "field[10,0.2;4,0.6;koleje;;",
+ data.fs_koleje or "",
+ "]container_end[]",
+ -- ----
+ "container[0.5,2.75]"..
+ "label[0,0.25;Formátování na cedule ({1}, {2} atd.):]"..
+ "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:;",
+ }
+ if data.fmt_radek ~= nil then
+ a(F(table.concat(data.fmt_radek, "\n")))
+ end
+ a("]textarea[0,3;13.25,1.5;fmt_prradek;formát prázdných řádků:;")
+ if data.fmt_prradek ~= nil then
+ a(F(table.concat(data.fmt_prradek, "\n")))
+ end
+ a{"]tooltip[fmt_radek;Uvedete-li více řádků\\, každý se použije jako formát pro odpovídající značku {N}\n"..
+ "ve formátu cedule a poslední se použije i pro všechny následující.]"..
+ "tooltip[fmt_prradek;V tomto poli se nenahrazují značky\\, text musí být uvedený tak\\, jak má být použit.\n"..
+ "Uvedete-li více řádků\\, každý se použije pro odpovídající značku {N} ve formátu cedule\n"..
+ "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í.]"..
+ "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}.)"),
+ "]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):]"..
+ "field[11.5,0.25;2,0.5;chat_dosah;;",
+ tostring(custom_state.chat_dosah or 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:]"..
+ "tablecolumns[text;text]"..
+ "table[0,0.75;14,2;texty;"}
+ for _, def in ipairs(hl_texty) do
+ 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(",")
+ end
+ formspec[#formspec] = ";"..(custom_state.tx_index or "").."]"
+ a("label[0.1,3.125;text:]".."field[0.75,2.75;10,0.75;preklad;;")
+ 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]
+ if s ~= nil then
+ a(F(s))
+ else
+ a(def.fs_default)
+ end
+ end
+ a( "]"..
+ "button[11,2.75;3,0.75;preklad_set;nastavit]"..
+ "tooltip[preklad;V levém sloupci tabulky jsou vzorové texty\\, v pravém sloupci jsou texty\\,\n"..
+ "které budou na jejich místě použity pro tento staniční rozhlas (ty můžete měnit).]"..
+ "textarea[0,3.5;14,1;;;příklad: ")
+ local hlaseni = sestavit_hlaseni(data, custom_state, {
+ LINKA = "S1",
+ VYCHOZI = "Praha hl. n.",
+ typ_zpozdeni = "+",
+ CIL = "Bratislava hl. st.",
+ NASL = "Pardubice hl. n.",
+ ODJZA = "60",
+ ZPOZDENI = "13",
+ JMVLAKU = "Testovací expres",
+ KOLEJ = "A",
+ })
+ a(F(hlaseni))
+ a("]container_end[]"--[[..
+ -- ----
+ "container[0.5,9.25]"..
+ "label[0,0.25;Formáty řádků ({1}, {2} atd.):]"..
+ "container_end[]" ]]
+ )
+ a("button[0.5,15;14,1;btn_save;Uložit]")
+ elseif page == PAGE_SETUP_2 then
+ elseif page == PAGE_IMPORT then
+ elseif page == PAGE_HELP then
+ elseif is_admin and page == PAGE_OWNERSHIP then
+ end
+ return table.concat(formspec)
+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 is_admin = custom_state.is_admin
+ local page = custom_state.page
+ local stn = custom_state.stn
+ local data = custom_state.data
+
+ if page == PAGE_SETUP_1 then
+ if
+ fields.dopravna and
+ fields.dopravna ~= tostring(custom_state.station_index) and
+ tonumber(fields.dopravna) ~= nil and
+ custom_state.stations[tonumber(fields.dopravna)] ~= nil
+ then
+ -- přepnout dopravnu
+ custom_state.station_index = tonumber(fields.dopravna)
+ end
+
+ -- zaškrtávací pole:
+ if fields.fn_firstupper then
+ data.fn_firstupper = ifthenelse(fields.fn_firstupper == "true", true, false)
+ end
+
+ -- koleje:
+ if fields.koleje and F(fields.koleje) ~= data.fs_koleje then
+ local parts = string.split(fields.koleje, ",", false)
+ local list, set = {}, {}
+ for _, part in ipairs(parts) do
+ if not set[part] then
+ set[part] = true
+ 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, ","))
+ end
+ if fields.fmt_negdelay then
+ data.fmt_negdelay = fields.fmt_negdelay
+ end
+ local fmt_ml_keys = {
+ "fmt_radek", "fmt_prradek",
+ }
+ for _, key in ipairs(fmt_ml_keys) do
+ local lines = fields[key]
+ if lines then
+ lines = string.split(lines, "\n", true)
+ assert(type(lines[1]) == "string")
+ data[key] = lines
+ 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 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)
+ stn = new_stn
+ custom_state.stn = new_stn
+ end
+ end
+ set_ann_data(stn, custom_state.epos, data)
+ end
+ elseif page == PAGE_SETUP_2 then
+ elseif page == PAGE_IMPORT then
+ elseif page == PAGE_HELP then
+ elseif page == PAGE_OWNERSHIP then
+ if is_admin then
+ -- TODO
+ end
+ end
+ if fields.tab then
+ -- přepnout stránku
+ local new_tab = tonumber(fields.tab)
+ if new_tab ~= nil and new_tab ~= page and (
+ new_tab == PAGE_SETUP_1 or new_tab == PAGE_SETUP_2 or new_tab == PAGE_IMPORT or new_tab == PAGE_HELP or
+ (is_admin and new_tab == PAGE_OWNERSHIP)
+ ) then
+ custom_state.page = new_tab
+ end
+ return get_setup_formspec(custom_state)
+ end
+ if not fields.quit then
+ return get_setup_formspec(custom_state)
+ end
+end
+
+local function can_dig(pos, player)
+ if player ~= nil and core.is_player(player) then
+ local owner = core.get_meta(pos):get_string("owner")
+ local player_name = player:get_player_name()
+ return owner == "" or owner == player_name or core.check_player_privs(player_name, "protection_bypass")
+ end
+ return false
+end
+
+local function on_construct(pos)
+ local meta = core.get_meta(pos)
+ meta:set_string("infotext", "staniční rozhlas")
+end
+
+local function on_destruct(pos)
+ local meta = core.get_meta(pos)
+ local stn = meta:get_string("stn")
+ if stn ~= "" then
+ local epos = advtrains.encode_pos(pos)
+ local stdata = advtrains.lines.stations[stn]
+ if stdata ~= nil then
+ (stdata.anns or {})[epos] = nil -- odstranit data staničního rozhlasu
+ end
+ end
+end
+
+local function on_dig(pos, node, digger)
+ -- TODO?
+ return core.node_dig(pos, node, digger)
+end
+
+local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
+ if clicker == nil or not clicker:is_player() then
+ return
+ end
+ local player_name = assert(clicker:get_player_name())
+ local meta = core.get_meta(pos)
+ local owner = meta:get_string("owner")
+ local stn = meta:get_string("stn")
+ if owner == "" or stn == "" then
+ if not core.check_player_privs(clicker, "railway_operator") then
+ core.chat_send_player(player_name, "*** K instalaci staničního rozhlasu je nutné právo railway_operator!")
+ return
+ end
+ local player_pos = vector.round(clicker:get_pos())
+ local limit = 256 * 256
+ local stations = advtrains.lines.load_stations_for_formspec()
+ local list = {}
+ for i, station_data in ipairs(stations) do
+ local d2 = limit
+ for _, stop in ipairs(station_data.tracks) do
+ local d2new = dist2(player_pos, stop.pos)
+ if d2new < d2 then
+ d2 = d2new
+ end
+ end
+ if d2 < limit then
+ table.insert(list, {
+ stn = assert(station_data.stn),
+ name = assert(station_data.name),
+ distance = math.floor(math.sqrt(d2)),
+ })
+ end
+ end
+ table.sort(list, function(a, b) return a.distance < b.distance end)
+ local custom_state = {
+ pos = pos,
+ epos = advtrains.encode_pos(pos),
+ list = list,
+ }
+ local formspec = {
+ "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]"..
+ "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]"..
+ "textlist[0.5,2.5;14,4;dopravna;",
+ }
+ if #list > 0 then
+ for i, candidate in ipairs(list) do
+ if i ~= 1 then
+ table.insert(formspec, ",")
+ end
+ table.insert(formspec, F(candidate.stn.." | "..candidate.name.." ("..candidate.distance.." m)"))
+ end
+ table.insert(formspec, ";1]")
+ else
+ table.insert(formspec, ";]")
+ end
+ ch_core.show_formspec(clicker, "advtrains_line_automation:init_rozhlas", table.concat(formspec), init_formspec_callback, custom_state, {})
+ return
+ end
+ if player_name ~= owner and not core.check_player_privs(player_name, "protection_bypass") then -- train_admin?
+ core.chat_send_player(player_name, "Nemáte oprávnění nastavovat tento staniční rozhlas!")
+ return
+ end
+ local epos = advtrains.encode_pos(pos)
+ 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!")
+ return
+ end
+ local stations = advtrains.lines.load_stations_for_formspec()
+ local selection_index
+ for i, station in ipairs(stations) do
+ if station.stn == stn then
+ selection_index = i
+ break
+ end
+ end
+ if selection_index == nil then
+ core.log("error", "Cannot determine selection index for the station '"..stn.."' in the list of stations!")
+ core.chat_send_player(player_name, "CHYBA: Vnitřní chyba: dopravna nenalezena ve výpisu!")
+ return
+ end
+ local custom_state = {
+ player_name = player_name,
+ is_admin = ch_core.get_player_role(player_name) == "admin",
+ pos = pos,
+ epos = epos,
+ owner = owner,
+ stn = assert(stn), -- kam byl staniční rozhlas dosud přiřazen
+ stations = stations, -- pro dropdown[]
+ station_index = selection_index, -- pro dropdown[]
+ data = assert(get_ann_data(stn, epos, true)),
+ page = PAGE_SETUP_1,
+ }
+ ch_core.show_formspec(clicker, "advtrains_line_automation:rozhlas", get_setup_formspec(custom_state),
+ setup_formspec_callback, custom_state, {})
+end
+
+def = {
+ description = "staniční rozhlas",
+ tiles = {{name = "blank.png^[noalpha"}}, -- TODO
+ drawtype = "normal",
+ paramtype = "light",
+ paramtype2 = "facedir", -- TODO: => colorfacedir
+ 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)
diff --git a/advtrains_line_automation/structs.md b/advtrains_line_automation/structs.md
index c265aa6..9b8d27d 100644
--- a/advtrains_line_automation/structs.md
+++ b/advtrains_line_automation/structs.md
@@ -99,6 +99,11 @@ station = {
}...
}
}
+ },
+ anns = { -- staniční rozhlasy
+ [encoded_pos] = {
+ ...
+ }
}
}