diff options
Diffstat (limited to 'advtrains_line_automation/stoprail.lua')
-rw-r--r-- | advtrains_line_automation/stoprail.lua | 299 |
1 files changed, 212 insertions, 87 deletions
diff --git a/advtrains_line_automation/stoprail.lua b/advtrains_line_automation/stoprail.lua index aa8dfdd..8553c97 100644 --- a/advtrains_line_automation/stoprail.lua +++ b/advtrains_line_automation/stoprail.lua @@ -1,6 +1,7 @@ -- stoprail.lua -- adds "stop rail". Recognized by lzb. (part of behavior is implemented there) +local rwt = assert(advtrains.lines.rwt) -- Translation S = attrans @@ -17,16 +18,39 @@ local function updatemeta(pos) local pe = advtrains.encode_pos(pos) local stdata = advtrains.lines.stops[pe] if not stdata then - meta:set_string("infotext", "Error") + meta:set_string("infotext", attrans("Error")) end + local stn = advtrains.lines.stations[stdata.stn] + local stn_viewname = stn and stn.name or "-" - meta:set_string("infotext", "Stn. "..stdata.stn.." T. "..stdata.track) + meta:set_string("infotext", attrans("Stn. @1 (@2) T. @3", stn_viewname, stdata.stn or "", stdata.track or "")) end local door_dropdown = {L=1, R=2, C=3} ---local door_dropdown_rev = {Right="R", Left="L", Closed="C"} -- Code review : why are the value in an order different than the one in the dropdown box ? local door_dropdown_code = {"L", "R", "C"} -- switch to numerical index of selection : for conversion of the numerical index in the opening side selection dropdown box to the internal codification +local function get_stn_dropdown(stn, player_name) + local stations = advtrains.lines.load_stations_for_formspec() + local selected_index + local result = {"dropdown[0.25,2;6,0.75;stn;(nepřiřazeno)"} + local right_mark + for i, st in ipairs(stations) do + if player_name ~= nil and player_name ~= st.owner then + right_mark = "(cizí) " + else + right_mark = "" + end + table.insert(result, ","..right_mark..minetest.formspec_escape(st.stn.." | "..st.name)) + if st.stn == stn then + selected_index = i + 1 + end + end + table.insert(result, ";"..(selected_index or "1")..";true]") + return table.concat(result) +end + +local player_to_stn_override = {} + local function show_stoprailform(pos, player) local pe = advtrains.encode_pos(pos) local pname = player:get_player_name() @@ -52,23 +76,67 @@ local function show_stoprailform(pos, player) stdata.speed = "M" end - local form = "size[8,7]" - form = form.."style[stn,ars;font=mono]" - form = form.."field[0.8,0.8;2,1;stn;"..S("Station Code")..";"..minetest.formspec_escape(stdata.stn).."]" - form = form.."field[2.8,0.8;5,1;stnname;"..S("Station Name")..";"..minetest.formspec_escape(stnname).."]" - form = form.."field[0.80,2.0;1.75,1;ddelay;"..S("Door Delay")..";"..minetest.formspec_escape(stdata.ddelay).."]" - form = form.."field[2.55,2.0;1.75,1;speed;"..S("Dep. Speed")..";"..minetest.formspec_escape(stdata.speed).."]" - form = form.."field[4.30,2.0;1.75,1;track;"..S("Track")..";"..minetest.formspec_escape(stdata.track).."]" - form = form.."field[6.05,2.0;1.75,1;wait;"..S("Stop Time")..";"..stdata.wait.."]" - form = form.."label[0.5,2.6;"..S("Door Side").."]" - form = form.."dropdown[0.51,3.0;2;doors;"..S("Left")..","..S("Right")..","..S("Closed")..";"..door_dropdown[stdata.doors]..";true]" -- switch to numerical index of the selection - form = form.."checkbox[3.00,2.4;reverse;"..S("Reverse train")..";"..(stdata.reverse and "true" or "false").."]" - form = form.."checkbox[3.00,2.8;kick;"..S("Kick out passengers")..";"..(stdata.kick and "true" or "false").."]" - form = form.."checkbox[3.00,3.2;waitsig;"..S("Wait for signal to clear")..";"..(stdata.waitsig and "true" or "false").."]" - form = form.."textarea[0.8,4.2;7,2;ars;"..S("Trains stopping here (ARS rules)")..";"..advtrains.interlocking.ars_to_text(stdata.ars).."]" - form = form.."button[0.5,6;7,1;save;"..S("Save").."]" - - minetest.show_formspec(pname, "at_lines_stop_"..pe, form) + local item_name = (minetest.registered_items["advtrains_line_automation:dtrack_stop_placer"] or {}).description or "" + local pname_unless_admin + if not minetest.check_player_privs(pname, "train_admin") then + pname_unless_admin = pname + end + local formspec = "formspec_version[4]".. + "size[8,12]".. + "item_image[0.25,0.25;1,1;advtrains_line_automation:dtrack_stop_placer]".. + "textarea[1.35,0.6;5.5,0.6;;;"..minetest.formspec_escape(string.format("%s %d,%d,%d", item_name, pos.x, pos.y, pos.z)).."]".. + "button_exit[7,0.25;0.75,0.75;close;X]".. + "style[ars,line,routingcode;font=mono]".. + "label[0.25,1.75;"..attrans("Station Code").." | "..attrans("Station Name").."]".. + get_stn_dropdown(player_to_stn_override[pname] or stdata.stn, pname_unless_admin).. + "field[6.75,2;1,0.75;track;"..attrans("Track")..";"..minetest.formspec_escape(stdata.track).."]".. + "label[0.25,3.4;"..attrans("Door Side").."]".. + "dropdown[2.25,3;2,0.75;doors;"..S("Left")..","..S("Right")..","..S("Closed")..";"..door_dropdown[stdata.doors]..";true]".. -- switch to numerical index of the selection + "checkbox[4.5,3.25;reverse;"..attrans("Reverse train")..";"..(stdata.reverse and "true" or "false").."]".. + "checkbox[4.5,3.75;kick;"..attrans("Kick out passengers")..";"..(stdata.kick and "true" or "false").."]".. + "checkbox[4.5,4.25;keepopen;Nezavírat dveře na odj.;"..(stdata.keepopen and "true" or "false").."]".. + "label[0.25,4.3;"..attrans("Stop Time").."]".. + "field[0.25,4.5;1,0.75;wait;;"..stdata.wait.."]".. + "label[1.5,4.9;+]".. + "field[2,4.5;1,0.75;ddelay;;"..minetest.formspec_escape(stdata.ddelay).."]".. -- "..attrans("Door Delay").." + (advtrains.lines.open_station_editor ~= nil and "button[3.5,4.5;4,0.75;editstn;Editor dopraven]" or "").. + "field[0.25,6;2,0.75;speed;"..attrans("Dep. Speed")..";"..minetest.formspec_escape(stdata.speed).."]".. + "field[2.5,6;2,0.75;line;Linka na odj.;"..minetest.formspec_escape(stdata.line or "").."]".. + "field[4.75,6;2,0.75;routingcode;Sm.kód na odj.;"..minetest.formspec_escape(stdata.routingcode or "").."]".. + "field[0.25,7.25;2,0.75;interval;Interval \\[s\\]:;"..minetest.formspec_escape(stdata.interval or "").."]".. + "field[2.5,7.25;2,0.75;ioffset;Jeho posun:;"..minetest.formspec_escape(stdata.ioffset or "0").."]".. + "button[4.75,7;3,1.0;ioffsetnow;Nastavit posun\nna odjezd teď + uložit]".. + "textarea[0.25,8.4;7.5,1.5;ars;"..attrans("Trains stopping here (ARS rules)")..";"..advtrains.interlocking.ars_to_text(stdata.ars).."]".. + "label[0.3,10.25;Platí jen pro vlaky s]".. + "field[3,10;1,0.5;minparts;;"..minetest.formspec_escape(stdata.minparts or "0").."]".. + "label[4.15,10.25;až]".. + "field[4.6,10;1,0.5;maxparts;;"..minetest.formspec_escape(stdata.maxparts or "128").."]".. + "label[5.75,10.25;vozy.]".. + "button_exit[0.25,11;7.5,0.75;save;"..attrans("Save").."]".. + "tooltip[close;Zavře dialogové okno]".. + "tooltip[stn;Dopravna\\, ke které tato zastávka patří. Jedna dopravna může mít víc kolejí. K vytvoření a úpravám dopraven použijte Editor dopraven.]".. + "tooltip[track;Číslo koleje]".. + "tooltip[wait;Základní doba stání s otevřenými dveřmi]".. + "tooltip[ddelay;Dodatečná doba stání před odjezdem po uzavření dveří]".. + "tooltip[speed;Cílová rychlost zastavivšího vlaku na odjezdu. Platné hodnoty jsou M pro nejvyšší rychlost vlaku a čísla 0 až 20.]".. + "tooltip[line;Nová linka na odjezdu. Prázdné pole = zachovat stávající linku. Pro smazání linky zadejte znak -]".. + "tooltip[routingcode;Nový směrový kód na odjezdu. Prázdné pole = zachovat stávající směrový kód. Pro smazání kódu vlaku zadejte znak -]".. + "tooltip[ars;Seznam podmínek\\, z nichž musí vlak splnit alespoň jednu\\, aby zde zastavil:\nLN {linka}\nRC {směrovací kód}\n".. + "* = jakýkoliv vlak\n\\# značí komentář a ! na začátku řádky danou podmínku neguje (nedoporučuje se)]".. + "tooltip[minparts;Minimální počet vozů\\, které musí vlak mít\\, aby zde zastavil. Výchozí hodnota je 0.]".. + "tooltip[maxparts;Maximální počet vozů\\, které vlak může mít\\, aby zde zastavil. Výchozí (a maximální) hodnota je 128.]".. + "tooltip[editsn;Otevře v novém okně editor dopraven.\nPoužijte tento editor pro založení nové dopravny\\, jíž budete moci přiřadit koleje.]".. + "tooltip[interval;Hodnota v sekundách 1 až 3600 nebo nevyplněno. Je-li vyplněno\\, rozdělí čas na intervaly zadané délky,\n".. + "a pokud z této zastávkové koleje v rámci jednoho z nich odjede vlak\\, odjezd dalšího bude pozdržen do začátku\n".. + "následujícího intervalu. Výchozí začátky intervalů stejné délky jsou v celé železniční síti společné.\n".. + "Slouží k nastavení intervalového provozu.]".. + "tooltip[ioffset;Hodnota v sekundách 0 až (interval - 1). Posune začátek intervalů oproti výchozímu stavu\n".. + "o zadaný počet sekund vpřed. Slouží k detailnímu vyladění času odjezdů relativně vůči ostatním linkám.]".. + "tooltip[ioffsetnow;Nastaví posun intervalu tak\\, aby pro tuto kolej nový interval začínal právě teď.\n".. + "Také uloží ostatní provedené změny.]" + + + minetest.show_formspec(pname, "at_lines_stop_"..pe, formspec) end local tmp_checkboxes = {} minetest.register_on_player_receive_fields(function(player, formname, fields) @@ -91,34 +159,54 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.reverse then tmp_checkboxes[pe].reverse = (fields.reverse == "true") end + if fields.keepopen then + tmp_checkboxes[pe].keepopen = (fields.keepopen == "true") + end if fields.waitsig then tmp_checkboxes[pe].waitsig = (fields.waitsig == "true") end - if fields.save then - if fields.stn and stdata.stn ~= fields.stn and fields.stn ~= "" then - local stn = advtrains.lines.stations[fields.stn] - if stn then - if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then - stdata.stn = fields.stn - else - minetest.chat_send_player(pname, S("Station code \"@1\" already exists and is owned by @2.", fields.stn, stn.owner)) - show_stoprailform(pos,player) - return - end - else - advtrains.lines.stations[fields.stn] = {name = fields.stnname, owner = pname} - stdata.stn = fields.stn - end + + if fields.stn then + local new_index = tonumber(fields.stn) + if new_index ~= nil then + player_to_stn_override[pname] = new_index + end + end + + local set_offset + + if fields.ioffsetnow and fields.interval ~= "" and fields.interval ~= "0" then + local interval = to_int(fields.interval) + if 0 < interval and interval <= 3600 then + local rwtime = rwt.to_secs(rwt.get_time()) + set_offset = rwtime % interval end - local stn = advtrains.lines.stations[stdata.stn] - if stn and fields.stnname and fields.stnname~="" and fields.stnname ~= stn.name then - if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then - stn.name = fields.stnname + end + + if fields.save or set_offset ~= nil then + local new_index = player_to_stn_override[pname] + if new_index ~= nil then + if new_index == 1 then + -- no name station + stdata.stn = "" + minetest.log("action", pname.." set track at "..minetest.pos_to_string(pos).." to no station.") else - minetest.chat_send_player(pname, S("This station is owned by @1. You are not allowed to edit its name.", stn.owner)) + local stations = advtrains.lines.load_stations_for_formspec() + local station = stations[new_index - 1] + if station ~= nil then + if station.owner == pname or minetest.check_player_privs(pname, "train_admin") then + stdata.stn = station.stn + minetest.log("action", pname.." set track at "..minetest.pos_to_string(pos).." to station '"..tostring(station.stn).."'.") + else + minetest.chat_send_player(pname, attrans("Station code '@1' does already exist and is owned by @2", station.stn, station.owner)) + show_stoprailform(pos,player) + return + end + end end + player_to_stn_override[pname] = nil end - + -- dropdowns if fields.doors then stdata.doors = door_dropdown_code[tonumber(fields.doors)] or "C" -- switch to numerical index of selection; attention : fields.doors is string typed, needed to be converted to an integer typed index in door_dropdown_code table @@ -141,6 +229,48 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.speed then stdata.speed = to_int(fields.speed) or "M" end + if fields.line then + stdata.line = fields.line + end + if fields.routingcode then + stdata.routingcode = fields.routingcode + end + if fields.minparts then + local v = to_int(fields.minparts) + if v <= 0 or v > 128 then v = nil end + stdata.minparts = v + end + if fields.maxparts then + local v = to_int(fields.maxparts) + if v <= 0 or v > 128 then v = nil end + stdata.maxparts = v + end + if fields.interval then + if fields.interval == "" or fields.interval == "0" then + stdata.interval = nil + else + local n = to_int(fields.interval) + if 0 < n and n <= 3600 then + stdata.interval = n + end + end + end + if stdata.interval == nil then + stdata.ioffset = nil + elseif set_offset ~= nil then + stdata.ioffset = set_offset + elseif fields.ioffset then + if fields.ioffset == "" or fields.ioffset == "0" then + stdata.ioffset = nil + else + local n = to_int(fields.ioffset) + if n > 0 then + stdata.ioffset = n % stdata.interval + else + stdata.ioffset = nil + end + end + end for k,v in pairs(tmp_checkboxes[pe]) do --handle checkboxes stdata[k] = v or nil @@ -148,13 +278,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) tmp_checkboxes[pe] = nil --TODO: signal updatemeta(pos) + minetest.log("action", pname.." saved stoprail at "..minetest.pos_to_string(pos)) show_stoprailform(pos, player) + elseif fields.editstn and advtrains.lines.open_station_editor ~= nil then + minetest.close_formspec(pname, formname) + minetest.after(0.25, advtrains.lines.open_station_editor, player) + return end end end) - local adefunc = function(def, preset, suffix, rotation) return { after_place_node=function(pos) @@ -168,59 +302,42 @@ local adefunc = function(def, preset, suffix, rotation) local pe = advtrains.encode_pos(pos) advtrains.lines.stops[pe] = nil end, + on_punch = function(pos, node, puncher, pointed_thing) + updatemeta(pos) + end, on_rightclick = function(pos, node, player) + if minetest.is_player(player) then + player_to_stn_override[player:get_player_name()] = nil + end show_stoprailform(pos, player) end, advtrains = { - on_train_approach = function(pos,train_id, train, index, has_entered) - if has_entered then return end -- do not stop again! - if train.path_cn[index] == 1 then - local pe = advtrains.encode_pos(pos) - local stdata = advtrains.lines.stops[pe] - if stdata and stdata.stn then - - --TODO REMOVE AFTER SOME TIME (only migration) - if not stdata.ars then - stdata.ars = {default=true} - end - if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then - advtrains.lzb_add_checkpoint(train, index, 2, nil) - local stn = advtrains.lines.stations[stdata.stn] - local stnname = stn and stn.name or S("Unknown Station") - train.text_inside = S("Next Stop:\n")..stnname - advtrains.interlocking.ars_set_disable(train, true) - end - end - end - end, - on_train_enter = function(pos, train_id, train, index) - if train.path_cn[index] == 1 then - local pe = advtrains.encode_pos(pos) - local stdata = advtrains.lines.stops[pe] - if not stdata then - return - end - - if stdata.ars and (stdata.ars.default or advtrains.interlocking.ars_check_rule_match(stdata.ars, train) ) then - local stn = advtrains.lines.stations[stdata.stn] - local stnname = stn and stn.name or S("Unknown Station") - - -- Send ATC command and set text - advtrains.atc.train_set_command(train, "B0 W O"..stdata.doors..(stdata.kick and "K" or "") - .." D"..stdata.wait.." "..(stdata.reverse and "R" or "") - .." A1 "..(stdata.waitsig and "G" or "") - .." OC D"..(stdata.ddelay or 1) .. " S" ..(stdata.speed or "M"), true) - train.text_inside = stnname - if tonumber(stdata.wait) then - minetest.after(tonumber(stdata.wait), function() train.text_inside = "" end) - end - end - end - end + on_train_approach = advtrains.lines.on_train_approach, + on_train_enter = advtrains.lines.on_train_enter, + on_train_leave = advtrains.lines.on_train_leave, }, } end +advtrains.station_stop_rail_additional_definition = adefunc -- HACK for tieless_tracks + +minetest.register_lbm({ + label = "Update line track metadata", + name = "advtrains_line_automation:update_metadata", + nodenames = { + "advtrains_line_automation:dtrack_stop_st", + "advtrains_line_automation:dtrack_stop_st_30", + "advtrains_line_automation:dtrack_stop_st_45", + "advtrains_line_automation:dtrack_stop_st_60", + "advtrains_line_automation:dtrack_stop_tieless_st", + "advtrains_line_automation:dtrack_stop_tieless_st_30", + "advtrains_line_automation:dtrack_stop_tieless_st_40", + "advtrains_line_automation:dtrack_stop_tieless_st_60", + }, + run_at_every_load = true, + action = updatemeta, +}) + if minetest.get_modpath("advtrains_train_track") ~= nil then advtrains.register_tracks("default", { nodename_prefix="advtrains_line_automation:dtrack_stop", @@ -232,4 +349,12 @@ if minetest.get_modpath("advtrains_train_track") ~= nil then formats={}, get_additional_definiton = adefunc, }, advtrains.trackpresets.t_30deg_straightonly) + + minetest.register_craft({ + output = "advtrains_line_automation:dtrack_stop_placer 2", + recipe = { + {"default:coal_lump", ""}, + {"advtrains:dtrack_placer", "advtrains:dtrack_placer"}, + }, + }) end |