From 5c8962b39bd4f6871ec87a988ac43d7bfad04d2b Mon Sep 17 00:00:00 2001 From: "Y. Wang" Date: Mon, 11 Apr 2022 16:55:50 +0200 Subject: Implement basic route signaling with Japanese signals for demo --- advtrains/init.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index a7e5764..1cba255 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -24,6 +24,9 @@ minetest.log("action", "[advtrains] Loading...") -- There is no need to support 0.4.x anymore given that the compatitability with it is already broken by 1bb1d825f46af3562554c12fba35a31b9f7973ff attrans = minetest.get_translator ("advtrains") +function attrans_formspec(...) + return minetest.formspec_escape(attrans(...)) +end --advtrains advtrains = {trains={}, player_to_train_mapping={}} @@ -199,6 +202,7 @@ advtrains.meseconrules = advtrains.fpath=minetest.get_worldpath().."/advtrains" advtrains.speed = dofile(advtrains.modpath.."/speed.lua") +advtrains.formspec = dofile(advtrains.modpath.."/formspec.lua") dofile(advtrains.modpath.."/path.lua") dofile(advtrains.modpath.."/trainlogic.lua") -- cgit v1.2.3 From f284d395d700ffb0fad29c18a9cfe466ed92961b Mon Sep 17 00:00:00 2001 From: orwell96 Date: Thu, 13 Jan 2022 21:03:55 +0100 Subject: Add TrackIterator interface as a common framework for walking along tracks (also for third-party libs) This will replace the interlocking traverser and will be used in the new itrainmap implementation --- advtrains/couple.lua | 4 +- advtrains/debugitems.lua | 37 ++++++++++++ advtrains/helpers.lua | 116 ++++++++++++++++++++++++++++++++++++ advtrains/init.lua | 3 + advtrains/settingtypes.txt | 4 ++ advtrains_interlocking/database.lua | 68 +++------------------ 6 files changed, 170 insertions(+), 62 deletions(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/couple.lua b/advtrains/couple.lua index 3e6c432..49c8a5d 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -475,7 +475,7 @@ minetest.register_entity("advtrains:couple", { self.object:remove() end, on_step=function(self, dtime) - if advtrains.wagon_outside_range(self.object:getpos()) then + if advtrains.wagon_outside_range(self.object:get_pos()) then --atdebug("Couple Removing outside range") self.object:remove() return @@ -514,7 +514,7 @@ minetest.register_entity("advtrains:couple", { tp2=advtrains.path_get_interpolated(train2, train2.end_index) end local pos_median=advtrains.pos_median(tp1, tp2) - if not vector.equals(pos_median, self.object:getpos()) then + if not vector.equals(pos_median, self.object:get_pos()) then self.object:set_pos(pos_median) end self.position_set=true diff --git a/advtrains/debugitems.lua b/advtrains/debugitems.lua index e598216..a59efc7 100644 --- a/advtrains/debugitems.lua +++ b/advtrains/debugitems.lua @@ -81,3 +81,40 @@ minetest.register_tool("advtrains:wagonpos_tester", end, } ) + + +local function trackitest(initial_pos, initial_connid) + local ti, pos, connid, ok + ti = advtrains.get_track_iterator(initial_pos, initial_connid, 500, true) + atdebug("Starting at pos:",initial_pos,initial_connid) + while ti:has_next_branch() do + pos, connid = ti:next_branch() -- in first iteration, this will be the node at initial_pos. In subsequent iterations this will be the switch node from which we are branching off + atdebug("Next Branch:",pos, connid) + ok = true + while ok do + ok, pos, connid = ti:next_track() + atdebug("Next Track:", ok, pos, connid) + end + end + atdebug("End of traverse. Visited: ",table.concat(ti.visited, ",")) +end + +minetest.register_tool("advtrains:trackitest", +{ + description = "Track Iterator Tester (leftclick conn 1, rightclick conn 2)", + groups = {cracky=1}, -- key=name, value=rating; rating=1..3. + inventory_image = "advtrains_track_swlcr_45.png", + wield_image = "advtrains_track_swlcr_45.png", + stack_max = 1, + range = 7.0, + + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then return end + trackitest(pointed_thing.under, 2) + end, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "node" then return end + trackitest(pointed_thing.under, 1) + end, +} +) diff --git a/advtrains/helpers.lua b/advtrains/helpers.lua index cf890ca..bef4903 100644 --- a/advtrains/helpers.lua +++ b/advtrains/helpers.lua @@ -470,3 +470,119 @@ else end end end + + +-- TrackIterator interface -- + +-- Metatable: +local trackiter_mt = { + -- get whether there are still unprocessed branches + has_next_branch = function(self) + return #self.branches > 0 + end, + -- go to the next unprocessed branch + -- returns track_pos, track_connid of the switch/crossing node where the track branches off + next_branch = function(self) + local br = table.remove(self.branches, 1) + -- Advance internal state + local adj_pos, adj_connid, _, _, adj_conns = advtrains.get_adjacent_rail(br.pos, nil, br.connid) + self.pos = adj_pos + self.bconnid = adj_connid + self.tconns = adj_conns + self.limit = br.limit - 1 + self.visited[advtrains.encode_pos(br.pos)] = true + return br.pos, br.connid + end, + -- get the next track along the current branch, + -- potentially adding branching tracks to the unprocessed branches list + -- returns status, track_pos, track_connid + -- status is true(ok), false(track has ended), nil(traversing limit has been reached) (when status~=true, track_pos and track_connid are nil) + next_track = function(self) + local pos = self.pos + if not pos then + -- last run found track end. Return false + return false, "track_end" + end + -- if limit hit, return nil to signal this + if self.limit <= 0 then + return nil, "limit_hit" + end + if self.visited[advtrains.encode_pos(pos)] then + -- node was already seen. do not continue + return nil, "already_visited" + end + -- select next conn (main conn to follow is the associated connection) + local mconnid = advtrains.get_matching_conn(self.bconnid, #self.tconns) + -- If there are more connections, add these to branches + for nconnid,_ in ipairs(self.tconns) do + if nconnid~=mconnid and nconnid~=self.bconnid then + table.insert(self.branches, {pos = self.pos, connid = nconnid, limit=self.limit}) + end + end + -- Advance internal state + local adj_pos, adj_connid, _, _, adj_conns = advtrains.get_adjacent_rail(pos, self.tconns, mconnid) + self.pos = adj_pos + self.bconnid = adj_connid + self.tconns = adj_conns + self.limit = self.limit - 1 + self.visited[advtrains.encode_pos(pos)] = true + return pos, mconnid + end, +} + +-- Returns a new TrackIterator object + +-- Parameters: +-- initial_pos: the initial track position of the track iterator +-- initial_connid: the connection index in which to traverse. If nil, adds a "branch" for every connection of the track (traverse in all directions) +-- limit: maximum distance from the start point after which the traverser stops +-- follow_all: if true, follows all branches at multi-connection tracks, even the ones pointing backwards or the crossing track on crossings. If false, follows only switches in driving direction. + +-- Functions of the returned TrackIterator can be called via the Lua : notation, such as ti:next_track() +-- If only the main track needs to be followed, use only the ti:next_track() function and do not call ti:next_branch(). +function advtrains.get_track_iterator(initial_pos, initial_connid, limit, follow_all) + local ti = { + visited = {} + } + if initial_connid then + ti.branches = { {pos = initial_pos, connid = initial_connid, limit=limit} } + else + -- get track info here + local node_ok, conns, rail_y=advtrains.get_rail_info_at(initial_pos) + assert(node_ok, "get_track_iterator called with non-track node!") + ti.branches = {} + for coni, _ in pairs(conns) do + table.insert(ti.branches, {pos = initial_pos, connid = coni, limit=limit}) + end + end + setmetatable(ti, {__index=trackiter_mt}) + return ti +end + +--[[ +Example TrackIterator usage structure: + +local ti, pos, connid, ok +ti = advtrains.get_track_iterator(initial_pos, initial_connid, 500, true) +while ti:has_next_branch() do + pos, connid = ti:next_branch() -- in first iteration, this will be the node at initial_pos. In subsequent iterations this will be the switch node from which we are branching off + repeat + + if then break end --for example, when traversing should stop at TCBs this can check if there is a tcb here + ok, pos, connid = ti:next_track() + until not ok -- this stops the loop when either the track end is reached or the limit is hit + -- while loop continues with the next branch ( diverging branch of one of the switches/crossings) until no more are left +end + +Example for walking only a single track (without branching): + +local ti, pos, connid, ok +ti = advtrains.get_track_iterator(initial_pos, initial_connid, 500, true) + +pos, connid = ti:next_branch() -- this always needs to be done at least one time, and gets the track at initial_pos +repeat + + if then break end --for example, when traversing should stop at TCBs this can check if there is a tcb here + ok, pos, connid = ti:next_track() +until not ok -- this stops the loop when either the track end is reached or the limit is hit +]] diff --git a/advtrains/init.lua b/advtrains/init.lua index a7e5764..2213937 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -229,6 +229,9 @@ end dofile(advtrains.modpath.."/lzb.lua") +if minetest.settings:get_bool("advtrains_register_debugitems") then + dofile(advtrains.modpath.."/debugitems.lua") +end --load/save diff --git a/advtrains/settingtypes.txt b/advtrains/settingtypes.txt index 2b627cb..79a1e4c 100644 --- a/advtrains/settingtypes.txt +++ b/advtrains/settingtypes.txt @@ -7,6 +7,10 @@ advtrains_show_ids (Show ID's in infotext) bool false # You probably want to leave this setting set to false. advtrains_enable_debugging (Enable debugging) bool false +# Register certain debug items, for example the tunnelborer +# Do not use on productive servers! +advtrains_register_debugitems (Register Debug Items) bool false + # Enable the logging of certain events related to advtrains # Logs are saved in the world directory as advtrains.log # This setting is useful for multiplayer servers diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index 6787c50..5f163e4 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -2,71 +2,19 @@ -- saving the location of TCB's, their neighbors and their state --[[ -== THIS COMMENT IS PARTIALLY INCORRECT AND OUTDATED! == - -The interlocking system is based on track circuits. -Track circuit breaks must be manually set by the user. Signals must be assigned to track circuit breaks and to a direction(connid). -To simplify the whole system, there is no overlap. -== Trains == -Trains always occupy certain track circuits. These are shown red in the signalbox view (TRAIN occupation entry). -== Database storage == -The things that are actually saved are the Track Circuit Breaks. Each TCB holds a list of the TCBs that are adjacent in each direction. -TC occupation/state is then saved inside each (TCB,Direction) and held in sync across all TCBs adjacent to this one. If something should not be in sync, -all entries are merged to perform the most restrictive setup. -== Traverser function == -To determine and update the list of neighboring TCBs, we need a traverser function. -It will start at one TCB in a specified direction (connid) and use get_adjacent_rail to crawl along the track. When encountering a turnout or a crossing, -it needs to branch(call itself recursively) to find all required TCBs. Those found TCBs are then saved in a list as tuples (TCB,Dir) -In the last step, they exchange their neighbors. -== TC states == -A track circuit does not have a state as such, but has more or less a list of "reservations" -type can be one of these: -TRAIN See Trains obove -ROUTE Route set from a signal, but no train has yet passed that signal. -Not implemented (see note by reversible): OWNED - former ROUTE segments that a train has begun passing (train_id assigned) - - Space behind a train up to the next signal, when a TC is set as REVERSIBLE -Certain TCs can be marked as "allow call-on". -== Route setting: == -Routes are set from a signal (the entry signal) to another signal facing the same direction (the exit signal) -Remember that signals are assigned to a TCB and a connid. -Whenever this is done, the following track circuits are set "reserved" by the train by saving the entry signal's ID: -- all TCs on the direct way of the route - set as ROUTE -Route setting fails whenever any TC that we want to set ROUTE to is already set ROUTE or TRAIN from another signal (except call-on, see below) -Apart from this, we need to set turnouts -- Turnouts on the track are set held as ROUTE -- Turnouts that purpose as flank protection are set held as FLANK (NOTE: left as an idea for later, because it's not clear how to do this properly without an engineer) -Note: In SimSig, it is possible to set a route into an still occupied section on the victoria line sim. (at the depot exit at seven sisters), although - there are still segments set ahead of the first train passing, remaining from another route. - Because our system will be able to remember "requested routes" and set them automatically once ready, this is not necessary here. -== Call-On/Multiple Trains == -It will be necessary to join and split trains using call-on routes. A call-on route may be set when: -- there are no ROUTE reservations -- there are TRAIN reservations only inside TCs that have "allow call-on" set -== TC Properties == -Note: Reversible property will not be implemented, assuming everything as non-rev. -This is sufficient to cover all use cases, and is done this way in reality. - REVERSIBLE - Whether trains are allowed to reverse while on track circuit - This property is supposed to be set for station tracks, where there is a signal at each end, and for sidings. - It should in no case be set for TCs covering turnouts, or for main running lines. - When a TC is not set as reversible, the OWNED status is cleared from the TC right after the train left it, - to allow other trains to pass it. - If it is set reversible, interlocking will keep the OWNED state behind the train up to the next signal, clearing it - as soon as the train passes another signal or enters a non-reversible section. -CALL_ON_ALLOWED - Whether this TC being blocked (TRAIN or ROUTE) does not prevent shunt routes being set through this TC -== More notes == -- It may not be possible to switch turnouts when their TC has any state entry - == Route releasing (TORR) == A train passing through a route happens as follows: Route set from entry to exit signal -Train passes entry signal and enters first TC past the signal --> Route from signal cleared (TCs remain locked) --> ROUTE status of first TC past signal cleared +Train passes entry signal and enters first TS past the signal +-> Route from signal cleared (TSs remain locked) +-> 'route' status of first TS past signal cleared +-> 'route_post' (holding the turnout locks) remains set Train continues along the route. -Whenever train leaves a TC +Whenever train leaves a TS -> Clearing any routes set from this TC outward recursively - see "Reversing problem" -Whenever train enters a TC --> Clear route status from the just entered TC +-> Free turnout locks and clear 'route_post' +Whenever train enters a TS +-> Clear route status from the just entered TC (but not route_post) Note that this prohibits by design that the train clears the route ahead of it. == Reversing Problem == Encountered at the Royston simulation in SimSig. It is solved there by imposing a time limit on the set route. Call-on routes can somehow be set anyway. -- cgit v1.2.3 From ad82b9cd4e12e16a176a2af08d480fa939076515 Mon Sep 17 00:00:00 2001 From: orwell Date: Sun, 15 Oct 2023 15:06:20 +0200 Subject: Forget it, and use the old preset tables for track registration. Just adapt it to the new definition. --- advtrains/init.lua | 1 + advtrains/track_reg_helper.lua | 743 ++++++++++++++++++++++++ advtrains/trackplacer.lua | 36 +- advtrains/tracks.lua | 24 +- advtrains_interlocking/init.lua | 3 +- advtrains_line_automation/init.lua | 3 +- advtrains_train_track/init.lua | 1122 ++++++++++++++++++++++++++++++------ advtrains_train_track/oldinit.lua | 937 ------------------------------ 8 files changed, 1720 insertions(+), 1149 deletions(-) create mode 100644 advtrains/track_reg_helper.lua mode change 100755 => 100644 advtrains_train_track/init.lua delete mode 100644 advtrains_train_track/oldinit.lua (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 2213937..78126e5 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -206,6 +206,7 @@ dofile(advtrains.modpath.."/trainhud.lua") dofile(advtrains.modpath.."/trackplacer.lua") dofile(advtrains.modpath.."/copytool.lua") dofile(advtrains.modpath.."/tracks.lua") +dofile(advtrains.modpath.."/track_reg_helper.lua") dofile(advtrains.modpath.."/occupation.lua") dofile(advtrains.modpath.."/atc.lua") dofile(advtrains.modpath.."/wagons.lua") diff --git a/advtrains/track_reg_helper.lua b/advtrains/track_reg_helper.lua new file mode 100644 index 0000000..ad73a40 --- /dev/null +++ b/advtrains/track_reg_helper.lua @@ -0,0 +1,743 @@ +-- New track registration helper +-- Retains the old table-template-based definition format, but adapts it to the new (advtrains 2.5) +-- track definition system +-- Note to future: This is actually just a work-saver, avoiding me to port over all the crossing nodes as well as the linetrack tracks. +-- Future track mods should please directly use the appropriate advtrains.register_node_4rot() API and not rely on this! + +--definition preparation +local function conns(c1, c2, r1, r2) return {{c=c1, y=r1}, {c=c2, y=r2}} end +local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end + +advtrains.ap={} +advtrains.ap.t_30deg_flat={ + v25_format = true, + regstep=1, + variant={ + st={ + conns = conns(0,8), + desc = "straight", + tpdouble = true, + tpsingle = true, + trackworker = "cr", + }, + cr={ + conns = conns(0,7), + desc = "curve", + tpdouble = true, + trackworker = "swlst", + }, + swlst={ + conns = conns3(0,8,7), + desc = "left switch (straight)", + trackworker = "swrst", + switchalt = "cr", + switchmc = "on", + switchst = "st", + switchprefix = "swl", + conn_map = {2,1,1}, + stmref = "swl", + }, + swlcr={ + conns = conns3(0,8,7), + desc = "left switch (curve)", + trackworker = "swrcr", + switchalt = "st", + switchmc = "off", + switchst = "cr", + switchprefix = "swl", + conn_map = {3,1,1}, + stmref = "swl", + }, + swrst={ + conns = conns3(0,8,9), + desc = "right switch (straight)", + trackworker = "st", + switchalt = "cr", + switchmc = "on", + switchst = "st", + switchprefix = "swr", + conn_map = {2,1,1}, + stmref = "swr", + }, + swrcr={ + conns = conns3(0,8,9), + desc = "right switch (curve)", + trackworker = "st", + switchalt = "st", + switchmc = "off", + switchst = "cr", + switchprefix = "swr", + conn_map = {3,1,1}, + stmref = "swr", + }, + }, + regtp=true, + tpdefault="st", + trackworker={ + ["swrcr"]="st", + ["swrst"]="st", + ["cr"]="swlst", + ["swlcr"]="swrcr", + ["swlst"]="swrst", + }, + rotation={"", "_30", "_45", "_60"}, + statemaps = { + swl = { st = "swlst", cr = "swlcr"}, + swr = { st = "swrst", cr = "swrcr"} + } +} +advtrains.ap.t_yturnout={ + v25_format = true, + regstep=1, + variant={ + l={ + conns = conns3(0,7,9), + desc = "Y-turnout (left)", + switchalt = "r", + switchmc = "off", + switchst = "l", + switchprefix = "", + conn_map = {2,1,1}, + stmref = "sw", + tpsingle = true, + }, + r={ + conns = conns3(0,7,9), + desc = "Y-turnout (right)", + switchalt = "l", + switchmc = "on", + switchst = "r", + switchprefix = "", + conn_map = {3,1,1}, + stmref = "sw", + } + }, + regtp=true, + tpdefault="l", + rotation={"", "_30", "_45", "_60"}, + statemaps = { + sw = { l = "l", r = "r"} + } +} +advtrains.ap.t_s3way={ + v25_format = true, + regstep=1, + variant={ + l={ + conns = { {c=0}, {c=7}, {c=8}, {c=9}}, + desc = "3-way turnout (left)", + switchalt = "s", + switchst="l", + switchprefix = "", + conn_map = {2,1,1}, + stmref = "sw", + }, + s={ + conns = { {c=0}, {c=7}, {c=8}, {c=9}}, + desc = "3-way turnout (straight)", + switchalt ="r", + switchst = "s", + switchprefix = "", + conn_map = {3,1,1}, + stmref = "sw", + tpsingle = true, + }, + r={ + conns = { {c=0}, {c=7}, {c=8}, {c=9}}, + desc = "3-way turnout (right)", + switchalt = "l", + switchst="r", + switchprefix = "", + conn_map = {4,1,1}, + stmref = "sw", + } + }, + regtp=true, + tpdefault="l", + rotation={"", "_30", "_45", "_60"}, + statemaps = { + sw = { l = "l", s = "s", r = "r"} + } +} +advtrains.ap.t_30deg_slope={ + v25_format = true, + regstep=1, + variant={ + vst1={conns = conns(8,0,0,0.5), rail_y = 0.25, desc = "steep uphill 1/2", slope=true}, + vst2={conns = conns(8,0,0.5,1), rail_y = 0.75, desc = "steep uphill 2/2", slope=true}, + vst31={conns = conns(8,0,0,0.33), rail_y = 0.16, desc = "uphill 1/3", slope=true}, + vst32={conns = conns(8,0,0.33,0.66), rail_y = 0.5, desc = "uphill 2/3", slope=true}, + vst33={conns = conns(8,0,0.66,1), rail_y = 0.83, desc = "uphill 3/3", slope=true}, + }, + regsp=true, + slopeplacer={ + [2]={"vst1", "vst2"}, + [3]={"vst31", "vst32", "vst33"}, + max=3,--highest entry + }, + slopeplacer_45={ + [2]={"vst1_45", "vst2_45"}, + max=2, + }, + rotation={"", "_30", "_45", "_60"}, + trackworker={}, + increativeinv={}, +} +advtrains.ap.t_30deg_straightonly={ + v25_format = true, + regstep=1, + variant={ + st={ + conns = conns(0,8), + desc = "straight", + tpdouble = true, + tpsingle = true, + trackworker = "st", + }, + }, + regtp=true, + tpdefault="st", + rotation={"", "_30", "_45", "_60"}, +} +advtrains.ap.t_30deg_straightonly_noplacer={ + v25_format = true, + regstep=1, + variant={ + st={ + conns = conns(0,8), + desc = "straight", + tpdouble = true, + tpsingle = true, + trackworker = "st", + }, + }, + tpdefault="st", + rotation={"", "_30", "_45", "_60"}, +} +advtrains.ap.t_45deg={ + v25_format = true, + regstep=2, + variant={ + st={ + conns = conns(0,8), + desc = "straight", + tpdouble = true, + tpsingle = true, + trackworker = "cr", + }, + cr={ + conns = conns(0,6), + desc = "curve", + tpdouble = true, + trackworker = "swlst", + }, + swlst={ + conns = conns3(0,8,6), + desc = "left switch (straight)", + trackworker = "swrst", + switchalt = "cr", + switchmc = "on", + switchst = "st", + }, + swlcr={ + conns = conns3(0,6,8), + desc = "left switch (curve)", + trackworker = "swrcr", + switchalt = "st", + switchmc = "off", + switchst = "cr", + }, + swrst={ + conns = conns3(0,8,10), + desc = "right switch (straight)", + trackworker = "st", + switchalt = "cr", + switchmc = "on", + switchst = "st", + }, + swrcr={ + conns = conns3(0,10,8), + desc = "right switch (curve)", + trackworker = "st", + switchalt = "st", + switchmc = "off", + switchst = "cr", + }, + }, + regtp=true, + tpdefault="st", + trackworker={ + ["swrcr"]="st", + ["swrst"]="st", + ["cr"]="swlst", + ["swlcr"]="swrcr", + ["swlst"]="swrst", + }, + rotation={"", "_30", "_45", "_60"}, +} +advtrains.ap.t_perpcrossing={ + v25_format = true, + regstep = 1, + variant={ + st={ + conns = { {c=0}, {c=8}, {c=4}, {c=12} }, + desc = "perpendicular crossing", + tpdouble = true, + tpsingle = true, + trackworker = "st", + conn_map = {2,1,4,3}, + }, + }, + regtp=true, + tpdefault="st", + rotation={"", "_30", "_45", "_60"}, +} +advtrains.ap.t_90plusx_crossing={ + v25_format = true, + regstep = 1, + variant={ + ["30l"]={ + conns = { {c=0}, {c=8}, {c=1}, {c=9} }, + desc = "30/90 degree crossing (left)", + tpdouble = true, + tpsingle = true, + trackworker = "45l", + conn_map = {2,1,4,3}, + }, + ["45l"]={ + conns = { {c=0}, {c=8}, {c=2}, {c=10} }, + desc = "45/90 degree crossing (left)", + tpdouble = true, + tpsingle = true, + trackworker = "60l", + conn_map = {2,1,4,3}, + }, + ["60l"]={ + conns = { {c=0}, {c=8}, {c=3}, {c=11}}, + desc = "60/90 degree crossing (left)", + tpdouble = true, + tpsingle = true, + trackworker = "60r", + conn_map = {2,1,4,3}, + }, + ["60r"]={ + conns = { {c=0}, {c=8}, {c=5}, {c=13} }, + desc = "60/90 degree crossing (right)", + tpdouble = true, + tpsingle = true, + trackworker = "45r", + conn_map = {2,1,4,3}, + }, + ["45r"]={ + conns = { {c=0}, {c=8}, {c=6}, {c=14} }, + desc = "45/90 degree crossing (right)", + tpdouble = true, + tpsingle = true, + trackworker = "30r", + conn_map = {2,1,4,3}, + }, + ["30r"]={ + conns = { {c=0}, {c=8}, {c=7}, {c=15}}, + desc = "30/90 degree crossing (right)", + tpdouble = true, + tpsingle = true, + trackworker = "30l", + conn_map = {2,1,4,3}, + }, + }, + regtp=true, + tpdefault="30l", + rotation={""}, + trackworker = { + ["30l"] = "45l", + ["45l"] = "60l", + ["60l"] = "60r", + ["60r"] = "45r", + ["45r"] = "30r", + ["30r"] = "30l", + } +} + +advtrains.ap.t_diagonalcrossing = { + v25_format = true, + regstep=1, + variant={ + ["30l45r"]={ + conns = {{c=1}, {c=9}, {c=6}, {c=14}}, + desc = "30left-45right diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="60l30l", + conn_map = {2,1,4,3}, + }, + ["60l30l"]={ + conns = {{c=3}, {c=11}, {c=1}, {c=9}}, + desc = "30left-60right diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="60l45r", + conn_map = {2,1,4,3}, + }, + ["60l45r"]={ + conns = {{c=3}, {c=11}, {c=6}, {c=14}}, + desc = "60left-45right diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="60l60r", + conn_map = {2,1,4,3}, + }, + ["60l60r"]={ + conns = {{c=3}, {c=11}, {c=5}, {c=13}}, + desc = "60left-60right diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="60r45l", + conn_map = {2,1,4,3}, + }, + --If 60l60r had a mirror image, it would be here, but it's symmetric. + -- 60l60r is also equivalent to 30l30r but rotated 90 degrees. + ["60r45l"]={ + conns = {{c=5}, {c=13}, {c=2}, {c=10}}, + desc = "60right-45left diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="60r30r", + conn_map = {2,1,4,3}, + }, + ["60r30r"]={ + conns = {{c=5}, {c=13}, {c=7}, {c=15}}, + desc = "60right-30right diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="30r45l", + conn_map = {2,1,4,3}, + }, + ["30r45l"]={ + conns = {{c=7}, {c=15}, {c=2}, {c=10}}, + desc = "30right-45left diagonal crossing", + tpdouble=true, + tpsingle=true, + trackworker="30l45r", + conn_map = {2,1,4,3}, + }, + + }, + regtp=true, + tpdefault="30l45r", + rotation={""}, + trackworker = { + ["30l45r"] = "60l30l", + ["60l30l"] = "60l45r", + ["60l45r"] = "60l60r", + ["60l60r"] = "60r45l", + ["60r45l"] = "60r30r", + ["60r30r"] = "30r45l", + ["30r45l"] = "30l45r", + } +} + +advtrains.trackpresets = advtrains.ap + +--definition format: ([] optional) +--[[{ + nodename_prefix + texture_prefix + [shared_texture] + models_prefix + models_suffix (with dot) + [shared_model] + formats={ + st,cr,swlst,swlcr,swrst,swrcr,vst1,vst2 + (each a table with indices 0-3, for if to register a rail with this 'rotation' table entry. nil is assumed as 'all', set {} to not register at all) + } + common={} change something on common rail appearance +} +[18.12.17] Note on new connection system: +In order to support real rail crossing nodes and finally make the trackplacer respect switches, I changed the connection system. +There can be a variable number of connections available. These are specified as tuples {c=, y=} +The table "at_conns" consists of {, ...} +the "at_rail_y" property holds the value that was previously called "railheight" +Depending on the number of connections: +2 conns: regular rail +3 conns: switch: + - when train passes in at conn1, will move out of conn2 + - when train passes in at conn2 or conn3, will move out of conn1 +4 conns: cross (or cross switch, depending on arrangement of conns): + - conn1 <> conn2 + - conn3 <> conn4 +]] + +-- Notify the user if digging the rail is not allowed +local function can_dig_callback(pos, player) + local ok, reason = advtrains.can_dig_or_modify_track(pos) + if not ok and player then + minetest.chat_send_player(player:get_player_name(), attrans("This track can not be removed!") .. " " .. reason) + end + return ok +end + +local function append_statemap_suffix(state_map, nnpref, rot) + local t = {} + for state, nn in pairs(state_map) do + t[state] = nnpref .. "_" .. nn .. rot + end + return t +end + +function advtrains.register_tracks(tracktype, def, preset) + if not preset.v25_format then + error("advtrains.register_tracks(): A track preset for pre-v2.5 is used with advtrains 2.5+. Mod probably defines own track preset instead of using it from the advtrains.ap table! Please check track mod compatibility!") + end + + if preset.regtp then + local nnprefix = def.nodename_prefix + minetest.register_craftitem(":"..nnprefix.."_placer", { + description = def.description, + inventory_image = def.texture_prefix.."_placer.png", + wield_image = def.texture_prefix.."_placer.png", + groups={advtrains_trackplacer=1, digtron_on_place=1}, + liquids_pointable = false, + on_place = function(itemstack, placer, pointed_thing) + local name = placer:get_player_name() + if not name then + return itemstack, false + end + if pointed_thing.type=="node" then + local pos=pointed_thing.above + local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0}) + if not advtrains.check_track_protection(pos, name) then + return itemstack, false + end + if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then + local s = minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable + if s then + -- minetest.chat_send_all(nnprefix) + local yaw = placer:get_look_horizontal() + advtrains.trackplacer.place_track(pos, nnprefix, name, yaw) + if not advtrains.is_creative(name) then + itemstack:take_item() + end + end + end + end + return itemstack, true + end, + }) + + advtrains.trackplacer.set_default_place_candidate(def.nodename_prefix, def.nodename_prefix.."_"..preset.tpdefault) + end + if preset.regsp then + advtrains.slope.register_placer(def, preset) + end + + for suffix, var in pairs(preset.variant) do + for rotid, rotation in ipairs(preset.rotation) do + if not def.formats[suffix] or def.formats[suffix][rotid] then + local img_suffix = suffix..rotation + local ndef = advtrains.merge_tables({ + description=def.description.."("..(var.desc or "any")..rotation..")", + drawtype = "mesh", + paramtype="light", + paramtype2="facedir", + walkable = false, + selection_box = { + type = "fixed", + fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2}, + }, + + mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix), + tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png"), def.second_texture}, + + groups = { + attached_node = advtrains.IGNORE_WORLD and 0 or 1, + advtrains_track=1, + ["advtrains_track_"..tracktype]=1, + save_in_at_nodedb=1, + dig_immediate=2, + not_in_creative_inventory=1, + not_blocking_trains=1, + }, + + can_dig = advtrains.track_can_dig_callback, + after_dig_node = advtrains.track_update_callback, + after_place_node = advtrains.track_update_callback, + + at_rail_y = var.rail_y + }, def.common or {}) + + if preset.regtp then + ndef.drop = def.nodename_prefix.."_placer" + end + if preset.regsp and var.slope then + ndef.drop = def.nodename_prefix.."_slopeplacer" + end + + --connections + ndef.at_conns = advtrains.rotate_conn_by(var.conns, (rotid-1)*preset.regstep) + -- NEW since 2.5 + ndef.at_conn_map = var.conn_map + + local ndef_avt_table = {} + + if var.switchalt and var.switchst then + -- NEW since 2.5 + ndef.on_rightclick = advtrains.state_node_on_rightclick_callback + ndef_avt_table.node_state = var.switchst + ndef_avt_table.node_next_state = var.switchalt + -- obtain and build statemap + local state_map = preset.statemaps[var.stmref] + if not state_map then error("On registering "..def.nodename_prefix.."_"..suffix..rotation..", stmref of variant doesn't reference entry in preset.statemaps") end + ndef_avt_table.node_state_map = append_statemap_suffix(state_map, def.nodename_prefix, rotation) + + if var.switchmc then + local vswitchalt = var.switchalt + ndef.mesecons = {effector = { + ["action_"..var.switchmc] = function(pos, node) + advtrains.setstate(pos, vswitchalt, node) + end, + rules=advtrains.meseconrules + }} + end + end + + local adef={} + if def.get_additional_definiton then + adef=def.get_additional_definiton(def, preset, suffix, rotation) + end + ndef = advtrains.merge_tables(ndef, adef) + + -- insert getstate/setstate functions after merging the additional definitions + if ndef_avt_table then + ndef.advtrains = advtrains.merge_tables(ndef.advtrains or {}, ndef_avt_table) + end + + -- NEW since 2.5: add appropriate fields for trackworker rotation + -- get the next rotation step + local num_rots = #preset.rotation + if rotid >= num_rots then + ndef.advtrains.trackworker_next_rot = def.nodename_prefix.."_"..suffix..preset.rotation[1] + ndef.advtrains.trackworker_rot_incr_param2 = true + else + ndef.advtrains.trackworker_next_rot = def.nodename_prefix.."_"..suffix..preset.rotation[rotid+1] + end + if var.trackworker then + ndef.advtrains.trackworker_next_var = def.nodename_prefix.."_"..var.trackworker..rotation + end + + local the_node_name = def.nodename_prefix.."_"..suffix..rotation + + --trackplacer + if preset.regtp and (var.tpsingle or var.tpdouble) then + advtrains.trackplacer.register_candidate( + def.nodename_prefix, + the_node_name, + ndef, + var.tpsingle, + var.tpdouble, + true) + end + + -- All set, go ahead and register node! + --atdebug("track_reg_helper: Registering ",the_node_name," as",ndef) + minetest.register_node(":"..the_node_name, ndef) + + end + end + end +end + +-- slope placer. Defined in register_tracks. +--crafted with rail and gravel +local sl={} +function sl.register_placer(def, preset) + minetest.register_craftitem(":"..def.nodename_prefix.."_slopeplacer",{ + description = attrans("@1 Slope", def.description), + inventory_image = def.texture_prefix.."_slopeplacer.png", + wield_image = def.texture_prefix.."_slopeplacer.png", + groups={}, + on_place = sl.create_slopeplacer_on_place(def, preset) + }) +end +--(itemstack, placer, pointed_thing) +function sl.create_slopeplacer_on_place(def, preset) + return function(istack, player, pt) + if not pt.type=="node" then + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node")) + return istack + end + local pos=pt.above + if not pos then + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node")) + return istack + end + local node=minetest.get_node(pos) + if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to then + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: space occupied!")) + return istack + end + if not advtrains.check_track_protection(pos, player:get_player_name()) then + minetest.record_protection_violation(pos, player:get_player_name()) + return istack + end + --determine player orientation (only horizontal component) + --get_look_horizontal may not be available + local yaw=player.get_look_horizontal and player:get_look_horizontal() or (player:get_look_yaw() - math.pi/2) + + --rounding unit vectors is a nice way for selecting 1 of 8 directions since sin(30°) is 0.5. + local dirvec={x=math.floor(math.sin(-yaw)+0.5), y=0, z=math.floor(math.cos(-yaw)+0.5)} + --translate to direction to look up inside the preset table + local param2, rot45=({ + [-1]={ + [-1]=2, + [0]=3, + [1]=3, + }, + [0]={ + [-1]=2, + [1]=0, + }, + [1]={ + [-1]=1, + [0]=1, + [1]=0, + }, + })[dirvec.x][dirvec.z], dirvec.x~=0 and dirvec.z~=0 + local lookup=preset.slopeplacer + if rot45 then lookup=preset.slopeplacer_45 end + + --go unitvector forward and look how far the next node is + local step=1 + while step<=lookup.max do + local node=minetest.get_node(vector.add(pos, dirvec)) + --next node solid? + if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to or advtrains.is_protected(pos, player:get_player_name()) then + --do slopes of this distance exist? + if lookup[step] then + if minetest.settings:get_bool("creative_mode") or istack:get_count()>=step then + --start placing + local placenodes=lookup[step] + while step>0 do + minetest.set_node(pos, {name=def.nodename_prefix.."_"..placenodes[step], param2=param2}) + if not minetest.settings:get_bool("creative_mode") then + istack:take_item() + end + step=step-1 + pos=vector.subtract(pos, dirvec) + end + else + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: Not enough slope items left (@1 required)", step)) + end + else + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: There's no slope of length @1",step)) + end + return istack + end + step=step+1 + pos=vector.add(pos, dirvec) + end + minetest.chat_send_player(player:get_player_name(), attrans("Can't place: no supporting node at upper end.")) + return itemstack + end +end + +advtrains.slope=sl diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua index 71eb79c..e6111dc 100644 --- a/advtrains/trackplacer.lua +++ b/advtrains/trackplacer.lua @@ -27,21 +27,27 @@ end -- Register a track node as candidate -- tpg: the track place group to register the candidates for +-- NOTE: This value is automatically added to the node definition (ndef) in field ndef.advtrains.track_place_group! -- name, ndef: the node name and node definition table to register -- as_single: whether the rail should be considered as candidate for one-endpoint connection -- Typically only set for the straight rail variants -- as_double: whether the rail should be considered as candidate for two-endpoint connection -- Typically set for straights and curves -function tp.register_candidate(tpg, name, ndef, as_single, as_double) +-- ignore_2conn_for_legacy_xing: skips the 2-connection assertion - ONLY for compatibility with the legacy crossing nodes, DO NOT USE! +function tp.register_candidate(tpg, name, ndef, as_single, as_double, ignore_2conn_for_legacy_xing) + --atdebug("TP Register candidate:",tpg, name, as_single, as_double) --get or create TP group if not tp.groups[tpg] then tp.groups[tpg] = {double = {}, single1 = {}, single2 = {}, default = {name = name, param2 = 0} } -- note: this causes the first candidate to ever be registered to be the default (which is typically what you want) + -- But it can be overwritten using tp.set_default_place_candidate end local g = tp.groups[tpg] -- get conns - assert(#ndef.at_conns == 2) + if not ignore_2conn_for_legacy_xing then + assert(#ndef.at_conns == 2) + end local c1, c2 = ndef.at_conns[1].c, ndef.at_conns[2].c local is_symmetrical = (rotate(c1, 8) == c2) @@ -59,6 +65,21 @@ function tp.register_candidate(tpg, name, ndef, as_single, as_double) g.single2[rotate(c2,i*4)] = {name=name, param2=i} end end + + -- Set track place group on the node + if not ndef.advtrains then + ndef.advtrains = {} + end + ndef.advtrains.track_place_group = tpg +end + +-- Sets the node that is placed by the track placer when there is no track nearby. param2 defaults to 0 +function tp.set_default_place_candidate(tpg, name, param2) + if not tp.groups[tpg] then + tp.groups[tpg] = {double = {}, single1 = {}, single2 = {}, default = {name = name, param2 = param2 or 0} } + else + tp.groups[tpg].default = {name = name, param2 = param2 or 0} + end end local function check_or_bend_rail(origin, dir, pname, commit) @@ -87,7 +108,7 @@ local function check_or_bend_rail(origin, dir, pname, commit) return false end -- now the track must be two-conn, else it wouldn't be allowed to have track_place_group set. - assert(#conns == 2) + --assert(#conns == 2) -- cannot check here, because of legacy crossing hack -- Is player and game allowed to do this? if not advtrains.can_dig_or_modify_track(pos) then return false @@ -132,6 +153,7 @@ local function check_or_bend_rail(origin, dir, pname, commit) end local function track_place_node(pos, node, ndef) + --atdebug("track_place_node: ",pos, node) advtrains.ndb.swap_node(pos, node) local ndef = minetest.registered_nodes[node.name] if ndef and ndef.after_place_node then @@ -151,14 +173,20 @@ end -- The function returns true on success. function tp.place_track(pos, tpg, pname, yaw) -- 1. collect neighboring tracks and whether they can be connected + --atdebug("tp.place_track(",pos, tpg, pname, yaw,")") local cand = {} for i=0,15 do if check_or_bend_rail(pos, i, pname) then cand[#cand+1] = i end end + --atdebug("Candidates: ",cand) -- obtain the group table local g = tp.groups[tpg] + if not g then + error("tp.place_track: for tpg="..tpg.." couldn't find the group table") + end + --atdebug("Group table:",g) -- 2. try all possible two-endpoint connections for k1, conn1 in ipairs(cand) do for k2, conn2 in ipairs(cand) do @@ -167,6 +195,7 @@ function tp.place_track(pos, tpg, pname, yaw) -- the combination the other way round will be run through in a later loop iteration if advtrains.yawToDirection(yaw, conn1, conn2) == conn2 then -- does there exist a suitable double-connection rail? + --atdebug("Try double conn: ",conn1, conn2) local node = g.double[conn1.."_"..conn2] if node then check_or_bend_rail(pos, conn1, pname, true) @@ -187,6 +216,7 @@ function tp.place_track(pos, tpg, pname, yaw) else single = g.single2 end + --atdebug("Try single conn: ",conn1) local node = single[conn1] if node then check_or_bend_rail(pos, conn1, pname, true) diff --git a/advtrains/tracks.lua b/advtrains/tracks.lua index 46ceaf8..1abef59 100644 --- a/advtrains/tracks.lua +++ b/advtrains/tracks.lua @@ -222,19 +222,6 @@ function advtrains.register_node_4rot(ori_name, ori_ndef, definition_mangling_fu end end - --- Registers an item to place and automatically connect nearby tracks -function advtrains.register_track_placer(...) - -end - --- Registers an item to place and adjust slope tracks -function advtrains.register_slope_placer(...) - -end - - - -- track-related helper functions function advtrains.is_track(nodename) @@ -255,13 +242,10 @@ function advtrains.get_track_connections(name, param2) if not param2 then noderot=0 end if noderot > 3 then atprint(" get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end - local tracktype - for k,_ in pairs(nodedef.groups) do - local tt=string.match(k, "^advtrains_track_(.+)$") - if tt then - tracktype=tt - end + if not nodedef.at_conns then + return nil end + --atdebug("Track connections of ",name,param2,":",nodedef.at_conns) return advtrains.rotate_conn_by(nodedef.at_conns, noderot*AT_CMAX/4), (nodedef.at_rail_y or 0), tracktype end @@ -283,4 +267,4 @@ function advtrains.can_dig_or_modify_track(pos) end end return true -end \ No newline at end of file +end diff --git a/advtrains_interlocking/init.lua b/advtrains_interlocking/init.lua index cc46b83..fe8b967 100644 --- a/advtrains_interlocking/init.lua +++ b/advtrains_interlocking/init.lua @@ -25,8 +25,7 @@ dofile(modpath.."tool.lua") dofile(modpath.."approach.lua") dofile(modpath.."ars.lua") ---TODO reenable tsr rail ---dofile(modpath.."tsr_rail.lua") +dofile(modpath.."tsr_rail.lua") minetest.register_privilege("interlocking", {description = "Can set up track sections, routes and signals.", give_to_singleplayer = true}) diff --git a/advtrains_line_automation/init.lua b/advtrains_line_automation/init.lua index cc8df3c..e7d0ea6 100644 --- a/advtrains_line_automation/init.lua +++ b/advtrains_line_automation/init.lua @@ -21,8 +21,7 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELI dofile(modpath.."railwaytime.lua") dofile(modpath.."scheduler.lua") ---TODO reenable stop rail ---dofile(modpath.."stoprail.lua") +dofile(modpath.."stoprail.lua") function advtrains.lines.load(data) diff --git a/advtrains_train_track/init.lua b/advtrains_train_track/init.lua old mode 100755 new mode 100644 index 6195b5b..5065155 --- a/advtrains_train_track/init.lua +++ b/advtrains_train_track/init.lua @@ -1,185 +1,937 @@ --- advtrains_train_track --- rewritten to work with advtrains 2.5 track system, but mimics the "old" template-based track registration --- Also, since 2.5, all tracks are moved here, even the ATC, LuaATC and Interlocking special tracks - -local function conns(c1, c2, r1, r2) return {{c=c1, y=r1}, {c=c2, y=r2}} end -local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end - - -local function register(reg) - for sgi, sgrp in ipairs(reg.sgroups) do - -- prepare the state map if we need it later - local state_map = {} - if sgrp.turnout then - for vn,var in pairs(sgrp.variants) do - local name = reg.base .. "_" .. vn - state_map[var.state] = name - end - end - -- iterate through each of the variants - for vn,var in pairs(sgrp.variants) do - local name = reg.base .. "_" .. vn - local ndef = { - description = reg.description .. " " .. vn, - drawtype = "mesh", - paramtype = "light", - paramtype2 = "facedir", - walkable = false, - selection_box = { - type = "fixed", - fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2}, - }, - - mesh_prefix=reg.mprefix.."_"..vn, - mesh_suffix = ".b3d", - tiles = { "advtrains_dtrack_shared.png" }, - - groups = { - advtrains_track=1, - advtrains_track_default=1, - dig_immediate=2, - --not_in_creative_inventory=1, - }, - - at_conns = sgrp.conns, - at_conn_map = var.conn_map, - - can_dig = advtrains.track_can_dig_callback, - after_dig_node = advtrains.track_update_callback, - after_place_node = advtrains.track_update_callback, - - advtrains = { - trackworker_next_var = reg.base .. "_" .. var.next_var - } - } - -- drop field - if reg.register_placer then - ndef.drop = reg.base.."_placer" - else - ndef.drop = reg.drop - end - -- if variant is suitable for autoplacing (trackplacer) - if var.track_place then - ndef.advtrains.track_place_group = reg.base - ndef.advtrains.track_place_single = var.track_place_single - end - -- turnout handling - -- if the containing group was a turnout group, the containing state_map will be used - if sgrp.turnout then - ndef.on_rightclick = advtrains.state_node_on_rightclick_callback - ndef.advtrains.node_state = var.state - ndef.advtrains.node_next_state = var.next_state - ndef.advtrains.node_state_map = state_map - end - -- use advtrains-internal function to register the 4 rotations of the node, to make our life easier - --atdebug("Registering: ",name, ndef) -- for debugging it can be useful to output what is being registered - advtrains.register_node_4rot(name, ndef) - end - end - if reg.register_placer then - local tpgrp = reg.base - minetest.register_craftitem(":advtrains:dtrack_placer", { - description = reg.description, - inventory_image = reg.mprefix.."_placer.png", - wield_image = reg.mprefix.."_placer.png", - groups={advtrains_trackplacer=1, digtron_on_place=1}, - liquids_pointable = false, - on_place = function(itemstack, placer, pointed_thing) - local name = placer:get_player_name() - if not name then - return itemstack, false - end - if pointed_thing.type=="node" then - local pos=pointed_thing.above - local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0}) - if not advtrains.check_track_protection(pos, name) then - return itemstack, false - end - if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then - local s = minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable - if s then - -- minetest.chat_send_all(nnprefix) - local yaw = placer:get_look_horizontal() - advtrains.trackplacer.place_track(pos, tpgrp, name, yaw) - if not advtrains.is_creative(name) then - itemstack:take_item() - end - end - end - end - return itemstack, true - end, - }) - end -end - - - --- normal dtrack -register({ - base = "advtrains:dtrack", - mprefix = "advtrains_dtrack", - description = attrans("Track"), - - sgroups = { -- integer-indexed table, we don't need a key here - -- inside are "variant" tables - { - variants = { - st = { - next_var = "cr", - track_place = true, - track_place_single = true, - }, - }, - conns = conns(0,8), - }, - { - variants = { - cr = { - next_var = "swlst", - track_place = true, - }, - }, - conns = conns(0,7), - }, - { - turnout = true, - variants = { - swlst = { - next_var = "swrst", - conn_map = {2,1,1}, - state = "st", - next_state = "cr", - }, - swlcr = { - next_var = "swrcr", - conn_map = {3,1,1}, - state = "cr", - next_state = "st", - }, - }, - conns = conns3(0,8,7), - }, - { - turnout = true, - variants = { - swrst = { - next_var = "st", - conn_map = {2,1,1}, - state = "st", - next_state = "cr", - }, - swrcr = { - next_var = "st", - conn_map = {3,1,1}, - state = "cr", - next_state = "st", - }, - }, - conns = conns3(0,8,9), - }, - }, - register_placer = true, -}) - ----------------------- \ No newline at end of file +-- Default tracks for advtrains +-- (c) orwell96 and contributors + +local default_boxen = { + ["st"] = { + [""] = { + selection_box = { + type = "fixed", + fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2}, + } + }, + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, + {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, + {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} + } + } + }, + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} + } + } + }, + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + }, + + ["cr"] = { + [""] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.5000, 0.6875, -0.3750, 0.5000}, + {-0.3750, -0.5000, -1.000, 1.000, -0.3750, 0.000} + } + } + }, + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.5000, 0.7500, -0.3750, 0.8750}, + {-0.3750, -0.5000, 0.8750, 0.2500, -0.3750, 1.188}, + {0.7500, -0.5000, 0.2500, 1.063, -0.3750, 0.8750} + } + } + }, + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.125, 0.5000, -0.3750, 0.6875}, + {-0.8750, -0.5000, -0.9375, -0.5000, -0.3750, 0.06250}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000} + } + } + }, + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.8125, -0.5000, -0.5000, 1.188, -0.3750, 0.5000}, + {-0.1875, -0.5000, 0.5000, 0.8750, -0.3125, 0.8750}, + {-0.2500, -0.5000, -0.9375, 0.3125, -0.3125, -0.5000} + } + } + }, + }, + + ["swlst"] = { + [""] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000}, + {-0.3125, -0.5000, -1.000, 0.9375, -0.3125, -0.06250} + } + } + }, + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, + {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, + {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} + } + } + }, + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.1875, 0.5000, -0.3750, 0.8750}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-0.8750, -0.5000, -0.8125, -0.5000, -0.3750, 0.5000} + } + } + }, + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + }, + + ["swrst"] = { + [""] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000}, + {-0.8125, -0.5000, -1.000, 0.4375, -0.3125, -0.06250} + } + } + }, + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, + {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, + {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} + } + } + }, + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.1875, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-0.5000, -0.5000, 0.5000, 0.5000, -0.3750, 0.8750}, + {-0.8125, -0.5000, -0.8750, 0.5000, -0.3750, -0.5000} + } + } + }, + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + }, +} + +default_boxen["swlcr"] = default_boxen["swlst"] +default_boxen["swrcr"] = default_boxen["swrst"] + +--flat +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack", + texture_prefix="advtrains_dtrack", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("Track"), + formats={}, + + get_additional_definiton = function(def, preset, suffix, rotation) + if default_boxen[suffix] ~= nil and default_boxen[suffix][rotation] ~= nil then + return default_boxen[suffix][rotation] + else + return {} + end + end, +}, advtrains.ap.t_30deg_flat) + +minetest.register_craft({ + output = 'advtrains:dtrack_placer 50', + recipe = { + {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, + {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, + {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, + }, +}) + +local y3_boxen = { + [""] = { + selection_box = { + type = "fixed", + fixed = { + {-0.8750, -0.5000, -1.125, 0.8750, -0.3750, 0.4375} + } + } + }, + + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625}, + {0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000}, + } + } + }, + + --UX FIXME: - 3way - have to place straight route before l and r or the + --nodebox overlaps too much and can't place the straight track node. + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.1250, 0.5000, -0.3750, 0.8750}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-1.1250, -0.5000, -0.9375, -0.5000, -0.3750, 0.5000} + } + } + }, + + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + --{-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000}, + {-0.875, -0.5000, -0.5, 1.0, -0.3750, 0.5}, + --{-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625}, + {-0.4375, -0.5000, -0.8750, 0.5625, -0.3750, -0.5000}, + --{0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000}, + {-0.2500, -0.5000, -0.2500, 1.0000, -0.3750, 0.8125}, + } + } + }, +} + + +local function y3_turnouts_addef(def, preset, suffix, rotation) + return y3_boxen[rotation] or {} +end +-- y-turnout +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_sy", + texture_prefix="advtrains_dtrack_sy", + models_prefix="advtrains_dtrack_sy", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("Y-turnout"), + formats = {}, + get_additional_definiton = y3_turnouts_addef, +}, advtrains.ap.t_yturnout) +minetest.register_craft({ + output = 'advtrains:dtrack_sy_placer 2', + recipe = { + {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, + {'', 'advtrains:dtrack_placer', ''}, + {'', 'advtrains:dtrack_placer', ''}, + }, +}) +--3-way turnout +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_s3", + texture_prefix="advtrains_dtrack_s3", + models_prefix="advtrains_dtrack_s3", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("3-way turnout"), + formats = {}, + get_additional_definiton = y3_turnouts_addef, +}, advtrains.ap.t_s3way) +minetest.register_craft({ + output = 'advtrains:dtrack_s3_placer 1', + recipe = { + {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, + {'', 'advtrains:dtrack_placer', ''}, + {'', '', ''}, + }, +}) + +-- Diamond Crossings + +local perp_boxen = { + [""] = {}, --default size + ["_30"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} + } + } + }, + ["_45"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.8125, -0.5000, -0.8125, 0.8125, -0.3750, 0.8125} + } + } + }, + ["_60"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} + } + } + }, +} + +-- perpendicular +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_xing", + texture_prefix="advtrains_dtrack_xing", + models_prefix="advtrains_dtrack_xing", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("Perpendicular Diamond Crossing Track"), + formats = {}, + get_additional_definiton = function(def, preset, suffix, rotation) + return perp_boxen[rotation] or {} + end +}, advtrains.ap.t_perpcrossing) + +minetest.register_craft({ + output = 'advtrains:dtrack_xing_placer 3', + recipe = { + {'', 'advtrains:dtrack_placer', ''}, + {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, + {'', 'advtrains:dtrack_placer', ''} + } +}) + +local ninety_plus_boxen = { + ["30l"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, + {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, + {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} + } + } + }, + ["30r"] = { + selection_box = { + type = "fixed", + fixed = { + {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000}, + {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500}, + {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000}, + {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000} + } + } + }, + ["45l"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} + } + } + }, + ["45r"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, + {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, + {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} + } + } + }, + ["60l"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + ["60r"] = { + selection_box = { + type = "fixed", + fixed = { + {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, + {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, + {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, + {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} + } + } + }, +} + +-- 90plusx +-- When you face east and param2=0, then this set of rails has a rail at 90 +-- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees. +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_xing90plusx", + texture_prefix="advtrains_dtrack_xing4590", + models_prefix="advtrains_dtrack_xing90plusx", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("90+Angle Diamond Crossing Track"), + formats = {}, + get_additional_definiton = function(def, preset, suffix, rotation) + return ninety_plus_boxen[suffix] or {} + end, +}, advtrains.ap.t_90plusx_crossing) +minetest.register_craft({ + output = 'advtrains:dtrack_xing90plusx_placer 2', + recipe = { + {'advtrains:dtrack_placer', '', ''}, + {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, + {'', '', 'advtrains:dtrack_placer'} + } +}) + +-- Deprecate any rails using the old name scheme +minetest.register_lbm({ + label = "Upgrade legacy 4590 rails", + name = "advtrains_train_track:replace_legacy_4590", + nodenames = {"advtrains:dtrack_xing4590_st"}, + run_at_every_load = true, + action = function(pos, node) + minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z) + minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2) + advtrains.ndb.swap_node(pos, + { + name="advtrains:dtrack_xing90plusx_45l", + param1=node.param1, + param2=node.param2, + }) + end +}) +-- This will replace any items left in the inventory +minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer") + +local diagonal_boxen = { + ["30r45l"] = { + selection_box = { + type = "fixed", + fixed = { + {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000}, + {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500}, + {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000}, + {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000} + } + } + }, + ["60l30l"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + ["60l60r"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} + } + } + }, + ["60r30r"] = { + selection_box = { + type = "fixed", + fixed = { + {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, + {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, + {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, + {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} + } + } + }, + ["30l45r"] = { + selection_box = { + type = "fixed", + fixed = { + {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, + {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, + {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, + {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} + } + } + }, + ["60l45r"] = { + selection_box = { + type = "fixed", + fixed = { + {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, + {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, + {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, + {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} + } + } + }, + ["60r45l"] = { + selection_box = { + type = "fixed", + fixed = { + {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, + {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, + {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, + {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} + } + } + }, +} + +-- Diagonal +-- This set of rail crossings is named based on the angle of each intersecting +-- direction when facing east and param2=0. Rails with l/r swapped are mirror +-- images. For example, 30r45l is the mirror image of 30l45r. +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_xingdiag", + texture_prefix="advtrains_dtrack_xingdiag", + models_prefix="advtrains_dtrack_xingdiag", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + description=attrans("Diagonal Diamond Crossing Track"), + formats = {}, + get_additional_definiton = function(def, preset, suffix, rotation) + return diagonal_boxen[suffix] or {} + end, +}, advtrains.ap.t_diagonalcrossing) +minetest.register_craft({ + output = 'advtrains:dtrack_xingdiag_placer 2', + recipe = { + {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, + {'', 'advtrains:dtrack_placer', ''}, + {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'} + } +}) +---- Not included: very shallow crossings like (30/60)+45. +---- At an angle of only 18.4 degrees, the models would not +---- translate well to a block game. +-- END crossings + +--slopes +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack", + texture_prefix="advtrains_dtrack", + models_prefix="advtrains_dtrack", + models_suffix=".obj", + shared_texture="advtrains_dtrack_shared.png", + second_texture="default_gravel.png", + description=attrans("Track"), + formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}}, +}, advtrains.ap.t_30deg_slope) + +minetest.register_craft({ + type = "shapeless", + output = 'advtrains:dtrack_slopeplacer 2', + recipe = { + "advtrains:dtrack_placer", + "advtrains:dtrack_placer", + "default:gravel", + }, +}) + + +--bumpers +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_bumper", + texture_prefix="advtrains_dtrack_bumper", + models_prefix="advtrains_dtrack_bumper", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_rail.png", + --bumpers still use the old texture until the models are redone. + description=attrans("Bumper"), + formats={}, +}, advtrains.ap.t_30deg_straightonly) +minetest.register_craft({ + output = 'advtrains:dtrack_bumper_placer 2', + recipe = { + {'group:wood', 'dye:red'}, + {'default:steel_ingot', 'default:steel_ingot'}, + {'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, + }, +}) +--legacy bumpers +for _,rot in ipairs({"", "_30", "_45", "_60"}) do + minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot) +end +-- atc track +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_atc", + texture_prefix="advtrains_dtrack_atc", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared_atc.png", + description=attrans("ATC controller"), + formats={}, + get_additional_definiton = advtrains.atc_function +}, advtrains.trackpresets.t_30deg_straightonly) + + +-- Tracks for loading and unloading trains +-- Copyright (C) 2017 Gabriel Pérez-Cerezo + +local function get_far_node(pos) + local node = minetest.get_node(pos) + if node.name == "ignore" then + minetest.get_voxel_manip():read_from_map(pos, pos) + node = minetest.get_node(pos) + end + return node +end + + +local function show_fc_formspec(pos,player) + local pname = player:get_player_name() + if minetest.is_protected(pos,pname) then + minetest.chat_send_player(pname, "Position is protected!") + return + end + + local meta = minetest.get_meta(pos) + local fc = meta:get_string("fc") or "" + + local form = 'formspec_version[4]'.. + 'size[10,5]'.. + 'label[0.5,0.4;Advtrains Loading/Unloading Track]'.. + 'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'.. + 'label[0.5,1.6;A blank field matches all wagons (default)]'.. + 'label[0.5,2.1;Use code # to disable the track section]'.. + 'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'.. + 'button[6.5,3;3,1;save;Submit]' + minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local pname = player:get_player_name() + local pe = string.match(formname, "^at_load_unload_(............)$") + local pos = advtrains.decode_pos(pe) + if pos then + if minetest.is_protected(pos, pname) then + minetest.chat_send_player(pname, "Position is protected!") + return + end + + if fields.save then + minetest.get_meta(pos):set_string("fc",tostring(fields.fc)) + minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc)) + show_fc_formspec(pos,player) + end + end +end) + + +local function train_load(pos, train_id, unload) + local train=advtrains.trains[train_id] + local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z}) + if not string.match(below.name, "chest") then + atprint("this is not a chest! at "..minetest.pos_to_string(pos)) + return + end + + local node_fc = minetest.get_meta(pos):get_string("fc") or "" + if node_fc == "#" then + --track section is disabled + return + end + + local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}}) + if inv and train.velocity < 2 then + for k, v in ipairs(train.trainparts) do + local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v}) + if i and i:get_list("box") then + + local wagon_data = advtrains.wagons[v] + local wagon_fc + if wagon_data.fc then + if not wagon_data.fcind then wagon_data.fcind = 1 end + wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or "" + end + + if node_fc == "" or wagon_fc == node_fc then + if not unload then + for _, item in ipairs(inv:get_list("main")) do + if i:get_list("box") and i:room_for_item("box", item) then + i:add_item("box", item) + inv:remove_item("main", item) + end + end + else + for _, item in ipairs(i:get_list("box")) do + if inv:get_list("main") and inv:room_for_item("main", item) then + i:remove_item("box", item) + inv:add_item("main", item) + end + end + end + end + end + end + end +end + + + +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_unload", + texture_prefix="advtrains_dtrack_unload", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared_unload.png", + description=attrans("Unloading Track"), + formats={}, + get_additional_definiton = function(def, preset, suffix, rotation) + return { + after_dig_node=function(pos) + advtrains.invalidate_all_paths() + advtrains.ndb.clear(pos) + end, + on_rightclick = function(pos, node, player) + show_fc_formspec(pos, player) + end, + advtrains = { + on_train_enter = function(pos, train_id) + train_load(pos, train_id, true) + end, + }, + } + end + }, advtrains.trackpresets.t_30deg_straightonly) +advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_load", + texture_prefix="advtrains_dtrack_load", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared_load.png", + description=attrans("Loading Track"), + formats={}, + get_additional_definiton = function(def, preset, suffix, rotation) + return { + after_dig_node=function(pos) + advtrains.invalidate_all_paths() + advtrains.ndb.clear(pos) + end, + on_rightclick = function(pos, node, player) + show_fc_formspec(pos, player) + end, + advtrains = { + on_train_enter = function(pos, train_id) + train_load(pos, train_id, false) + end, + }, + } + end + }, advtrains.trackpresets.t_30deg_straightonly) + +-- mod-dependent crafts +local loader_core = "default:mese_crystal" --fallback +if minetest.get_modpath("basic_materials") then + loader_core = "basic_materials:ic" +elseif minetest.get_modpath("technic") then + loader_core = "technic:control_logic_unit" +end +--print("Loader Core: "..loader_core) + +minetest.register_craft({ + type="shapeless", + output = 'advtrains:dtrack_load_placer', + recipe = { + "advtrains:dtrack_placer", + loader_core, + "default:chest" + }, +}) +loader_core = nil --nil the crafting variable + +--craft between load/unload tracks +minetest.register_craft({ + type="shapeless", + output = 'advtrains:dtrack_unload_placer', + recipe = { + "advtrains:dtrack_load_placer", + }, +}) +minetest.register_craft({ + type="shapeless", + output = 'advtrains:dtrack_load_placer', + recipe = { + "advtrains:dtrack_unload_placer", + }, +}) + + +if mesecon then + advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_detector_off", + texture_prefix="advtrains_dtrack_detector", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared_detector_off.png", + description=attrans("Detector Rail"), + formats={}, + get_additional_definiton = function(def, preset, suffix, rotation) + return { + mesecons = { + receptor = { + state = mesecon.state.off, + rules = advtrains.meseconrules + } + }, + advtrains = { + on_updated_from_nodedb = function(pos, node) + mesecon.receptor_off(pos, advtrains.meseconrules) + end, + on_train_enter=function(pos, train_id) + advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) + if advtrains.is_node_loaded(pos) then + mesecon.receptor_on(pos, advtrains.meseconrules) + end + end + } + } + end + }, advtrains.ap.t_30deg_straightonly) + advtrains.register_tracks("default", { + nodename_prefix="advtrains:dtrack_detector_on", + texture_prefix="advtrains_dtrack", + models_prefix="advtrains_dtrack", + models_suffix=".b3d", + shared_texture="advtrains_dtrack_shared_detector_on.png", + description="Detector(on)(you hacker you)", + formats={}, + get_additional_definiton = function(def, preset, suffix, rotation) + return { + mesecons = { + receptor = { + state = mesecon.state.on, + rules = advtrains.meseconrules + } + }, + advtrains = { + on_updated_from_nodedb = function(pos, node) + mesecon.receptor_on(pos, advtrains.meseconrules) + end, + on_train_leave=function(pos, train_id) + advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) + if advtrains.is_node_loaded(pos) then + mesecon.receptor_off(pos, advtrains.meseconrules) + end + end + } + } + end + }, advtrains.ap.t_30deg_straightonly_noplacer) +minetest.register_craft({ + type="shapeless", + output = 'advtrains:dtrack_detector_off_placer', + recipe = { + "advtrains:dtrack_placer", + "mesecons:wire_00000000_off" + }, +}) +end +--TODO legacy +--I know lbms are better for this purpose +for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="swrcr", }) do + minetest.register_abm({ + -- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_"..name}, + interval = 1.0, -- Operation interval in seconds + chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep, param2=node.param2}) end, + }) + minetest.register_abm({ + -- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_"..name.."_45"}, + interval = 1.0, -- Operation interval in seconds + chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep.."_45", param2=node.param2}) end, + }) +end + +if advtrains.register_replacement_lbms then +minetest.register_lbm({ + name = "advtrains:ramp_replacement_1", +-- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_vert1"}, + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst1", param2=(node.param2+2)%4}) end, +}) +minetest.register_lbm({ + name = "advtrains:ramp_replacement_1", +-- -- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_vert2"}, + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end, +}) + minetest.register_abm({ + name = "advtrains:st_rep_1", + -- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_st"}, + interval=1, + chance=1, + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st", param2=node.param2}) end, + }) + minetest.register_lbm({ + name = "advtrains:st_rep_1", + -- -- In the following two fields, also group:groupname will work. + nodenames = {"advtrains:track_st_45"}, + action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st_45", param2=node.param2}) end, + }) +end diff --git a/advtrains_train_track/oldinit.lua b/advtrains_train_track/oldinit.lua deleted file mode 100644 index 5065155..0000000 --- a/advtrains_train_track/oldinit.lua +++ /dev/null @@ -1,937 +0,0 @@ --- Default tracks for advtrains --- (c) orwell96 and contributors - -local default_boxen = { - ["st"] = { - [""] = { - selection_box = { - type = "fixed", - fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2}, - } - }, - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, - {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, - {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} - } - } - }, - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} - } - } - }, - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - }, - - ["cr"] = { - [""] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.5000, 0.6875, -0.3750, 0.5000}, - {-0.3750, -0.5000, -1.000, 1.000, -0.3750, 0.000} - } - } - }, - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.5000, 0.7500, -0.3750, 0.8750}, - {-0.3750, -0.5000, 0.8750, 0.2500, -0.3750, 1.188}, - {0.7500, -0.5000, 0.2500, 1.063, -0.3750, 0.8750} - } - } - }, - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.125, 0.5000, -0.3750, 0.6875}, - {-0.8750, -0.5000, -0.9375, -0.5000, -0.3750, 0.06250}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000} - } - } - }, - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.8125, -0.5000, -0.5000, 1.188, -0.3750, 0.5000}, - {-0.1875, -0.5000, 0.5000, 0.8750, -0.3125, 0.8750}, - {-0.2500, -0.5000, -0.9375, 0.3125, -0.3125, -0.5000} - } - } - }, - }, - - ["swlst"] = { - [""] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000}, - {-0.3125, -0.5000, -1.000, 0.9375, -0.3125, -0.06250} - } - } - }, - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, - {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, - {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} - } - } - }, - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.1875, 0.5000, -0.3750, 0.8750}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-0.8750, -0.5000, -0.8125, -0.5000, -0.3750, 0.5000} - } - } - }, - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - }, - - ["swrst"] = { - [""] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000}, - {-0.8125, -0.5000, -1.000, 0.4375, -0.3125, -0.06250} - } - } - }, - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, - {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, - {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} - } - } - }, - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.1875, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-0.5000, -0.5000, 0.5000, 0.5000, -0.3750, 0.8750}, - {-0.8125, -0.5000, -0.8750, 0.5000, -0.3750, -0.5000} - } - } - }, - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - }, -} - -default_boxen["swlcr"] = default_boxen["swlst"] -default_boxen["swrcr"] = default_boxen["swrst"] - ---flat -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack", - texture_prefix="advtrains_dtrack", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("Track"), - formats={}, - - get_additional_definiton = function(def, preset, suffix, rotation) - if default_boxen[suffix] ~= nil and default_boxen[suffix][rotation] ~= nil then - return default_boxen[suffix][rotation] - else - return {} - end - end, -}, advtrains.ap.t_30deg_flat) - -minetest.register_craft({ - output = 'advtrains:dtrack_placer 50', - recipe = { - {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, - {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, - {'default:steel_ingot', 'group:stick', 'default:steel_ingot'}, - }, -}) - -local y3_boxen = { - [""] = { - selection_box = { - type = "fixed", - fixed = { - {-0.8750, -0.5000, -1.125, 0.8750, -0.3750, 0.4375} - } - } - }, - - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625}, - {0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000}, - } - } - }, - - --UX FIXME: - 3way - have to place straight route before l and r or the - --nodebox overlaps too much and can't place the straight track node. - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.1250, 0.5000, -0.3750, 0.8750}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-1.1250, -0.5000, -0.9375, -0.5000, -0.3750, 0.5000} - } - } - }, - - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - --{-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000}, - {-0.875, -0.5000, -0.5, 1.0, -0.3750, 0.5}, - --{-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625}, - {-0.4375, -0.5000, -0.8750, 0.5625, -0.3750, -0.5000}, - --{0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000}, - {-0.2500, -0.5000, -0.2500, 1.0000, -0.3750, 0.8125}, - } - } - }, -} - - -local function y3_turnouts_addef(def, preset, suffix, rotation) - return y3_boxen[rotation] or {} -end --- y-turnout -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_sy", - texture_prefix="advtrains_dtrack_sy", - models_prefix="advtrains_dtrack_sy", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("Y-turnout"), - formats = {}, - get_additional_definiton = y3_turnouts_addef, -}, advtrains.ap.t_yturnout) -minetest.register_craft({ - output = 'advtrains:dtrack_sy_placer 2', - recipe = { - {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, - {'', 'advtrains:dtrack_placer', ''}, - {'', 'advtrains:dtrack_placer', ''}, - }, -}) ---3-way turnout -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_s3", - texture_prefix="advtrains_dtrack_s3", - models_prefix="advtrains_dtrack_s3", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("3-way turnout"), - formats = {}, - get_additional_definiton = y3_turnouts_addef, -}, advtrains.ap.t_s3way) -minetest.register_craft({ - output = 'advtrains:dtrack_s3_placer 1', - recipe = { - {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, - {'', 'advtrains:dtrack_placer', ''}, - {'', '', ''}, - }, -}) - --- Diamond Crossings - -local perp_boxen = { - [""] = {}, --default size - ["_30"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} - } - } - }, - ["_45"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.8125, -0.5000, -0.8125, 0.8125, -0.3750, 0.8125} - } - } - }, - ["_60"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} - } - } - }, -} - --- perpendicular -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_xing", - texture_prefix="advtrains_dtrack_xing", - models_prefix="advtrains_dtrack_xing", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("Perpendicular Diamond Crossing Track"), - formats = {}, - get_additional_definiton = function(def, preset, suffix, rotation) - return perp_boxen[rotation] or {} - end -}, advtrains.ap.t_perpcrossing) - -minetest.register_craft({ - output = 'advtrains:dtrack_xing_placer 3', - recipe = { - {'', 'advtrains:dtrack_placer', ''}, - {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, - {'', 'advtrains:dtrack_placer', ''} - } -}) - -local ninety_plus_boxen = { - ["30l"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, - {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, - {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} - } - } - }, - ["30r"] = { - selection_box = { - type = "fixed", - fixed = { - {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000}, - {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500}, - {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000}, - {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000} - } - } - }, - ["45l"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} - } - } - }, - ["45r"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750}, - {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}, - {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000} - } - } - }, - ["60l"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - ["60r"] = { - selection_box = { - type = "fixed", - fixed = { - {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, - {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, - {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, - {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} - } - } - }, -} - --- 90plusx --- When you face east and param2=0, then this set of rails has a rail at 90 --- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees. -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_xing90plusx", - texture_prefix="advtrains_dtrack_xing4590", - models_prefix="advtrains_dtrack_xing90plusx", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("90+Angle Diamond Crossing Track"), - formats = {}, - get_additional_definiton = function(def, preset, suffix, rotation) - return ninety_plus_boxen[suffix] or {} - end, -}, advtrains.ap.t_90plusx_crossing) -minetest.register_craft({ - output = 'advtrains:dtrack_xing90plusx_placer 2', - recipe = { - {'advtrains:dtrack_placer', '', ''}, - {'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, - {'', '', 'advtrains:dtrack_placer'} - } -}) - --- Deprecate any rails using the old name scheme -minetest.register_lbm({ - label = "Upgrade legacy 4590 rails", - name = "advtrains_train_track:replace_legacy_4590", - nodenames = {"advtrains:dtrack_xing4590_st"}, - run_at_every_load = true, - action = function(pos, node) - minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z) - minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2) - advtrains.ndb.swap_node(pos, - { - name="advtrains:dtrack_xing90plusx_45l", - param1=node.param1, - param2=node.param2, - }) - end -}) --- This will replace any items left in the inventory -minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer") - -local diagonal_boxen = { - ["30r45l"] = { - selection_box = { - type = "fixed", - fixed = { - {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000}, - {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500}, - {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000}, - {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000} - } - } - }, - ["60l30l"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - ["60l60r"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000} - } - } - }, - ["60r30r"] = { - selection_box = { - type = "fixed", - fixed = { - {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, - {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, - {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, - {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} - } - } - }, - ["30l45r"] = { - selection_box = { - type = "fixed", - fixed = { - {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000}, - {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500}, - {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000}, - {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000} - } - } - }, - ["60l45r"] = { - selection_box = { - type = "fixed", - fixed = { - {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000}, - {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000}, - {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750}, - {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875} - } - } - }, - ["60r45l"] = { - selection_box = { - type = "fixed", - fixed = { - {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000}, - {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000}, - {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750}, - {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875} - } - } - }, -} - --- Diagonal --- This set of rail crossings is named based on the angle of each intersecting --- direction when facing east and param2=0. Rails with l/r swapped are mirror --- images. For example, 30r45l is the mirror image of 30l45r. -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_xingdiag", - texture_prefix="advtrains_dtrack_xingdiag", - models_prefix="advtrains_dtrack_xingdiag", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - description=attrans("Diagonal Diamond Crossing Track"), - formats = {}, - get_additional_definiton = function(def, preset, suffix, rotation) - return diagonal_boxen[suffix] or {} - end, -}, advtrains.ap.t_diagonalcrossing) -minetest.register_craft({ - output = 'advtrains:dtrack_xingdiag_placer 2', - recipe = { - {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}, - {'', 'advtrains:dtrack_placer', ''}, - {'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'} - } -}) ----- Not included: very shallow crossings like (30/60)+45. ----- At an angle of only 18.4 degrees, the models would not ----- translate well to a block game. --- END crossings - ---slopes -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack", - texture_prefix="advtrains_dtrack", - models_prefix="advtrains_dtrack", - models_suffix=".obj", - shared_texture="advtrains_dtrack_shared.png", - second_texture="default_gravel.png", - description=attrans("Track"), - formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}}, -}, advtrains.ap.t_30deg_slope) - -minetest.register_craft({ - type = "shapeless", - output = 'advtrains:dtrack_slopeplacer 2', - recipe = { - "advtrains:dtrack_placer", - "advtrains:dtrack_placer", - "default:gravel", - }, -}) - - ---bumpers -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_bumper", - texture_prefix="advtrains_dtrack_bumper", - models_prefix="advtrains_dtrack_bumper", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_rail.png", - --bumpers still use the old texture until the models are redone. - description=attrans("Bumper"), - formats={}, -}, advtrains.ap.t_30deg_straightonly) -minetest.register_craft({ - output = 'advtrains:dtrack_bumper_placer 2', - recipe = { - {'group:wood', 'dye:red'}, - {'default:steel_ingot', 'default:steel_ingot'}, - {'advtrains:dtrack_placer', 'advtrains:dtrack_placer'}, - }, -}) ---legacy bumpers -for _,rot in ipairs({"", "_30", "_45", "_60"}) do - minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot) -end --- atc track -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_atc", - texture_prefix="advtrains_dtrack_atc", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared_atc.png", - description=attrans("ATC controller"), - formats={}, - get_additional_definiton = advtrains.atc_function -}, advtrains.trackpresets.t_30deg_straightonly) - - --- Tracks for loading and unloading trains --- Copyright (C) 2017 Gabriel Pérez-Cerezo - -local function get_far_node(pos) - local node = minetest.get_node(pos) - if node.name == "ignore" then - minetest.get_voxel_manip():read_from_map(pos, pos) - node = minetest.get_node(pos) - end - return node -end - - -local function show_fc_formspec(pos,player) - local pname = player:get_player_name() - if minetest.is_protected(pos,pname) then - minetest.chat_send_player(pname, "Position is protected!") - return - end - - local meta = minetest.get_meta(pos) - local fc = meta:get_string("fc") or "" - - local form = 'formspec_version[4]'.. - 'size[10,5]'.. - 'label[0.5,0.4;Advtrains Loading/Unloading Track]'.. - 'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'.. - 'label[0.5,1.6;A blank field matches all wagons (default)]'.. - 'label[0.5,2.1;Use code # to disable the track section]'.. - 'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'.. - 'button[6.5,3;3,1;save;Submit]' - minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form) -end - -minetest.register_on_player_receive_fields(function(player, formname, fields) - local pname = player:get_player_name() - local pe = string.match(formname, "^at_load_unload_(............)$") - local pos = advtrains.decode_pos(pe) - if pos then - if minetest.is_protected(pos, pname) then - minetest.chat_send_player(pname, "Position is protected!") - return - end - - if fields.save then - minetest.get_meta(pos):set_string("fc",tostring(fields.fc)) - minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc)) - show_fc_formspec(pos,player) - end - end -end) - - -local function train_load(pos, train_id, unload) - local train=advtrains.trains[train_id] - local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z}) - if not string.match(below.name, "chest") then - atprint("this is not a chest! at "..minetest.pos_to_string(pos)) - return - end - - local node_fc = minetest.get_meta(pos):get_string("fc") or "" - if node_fc == "#" then - --track section is disabled - return - end - - local inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}}) - if inv and train.velocity < 2 then - for k, v in ipairs(train.trainparts) do - local i=minetest.get_inventory({type="detached", name="advtrains_wgn_"..v}) - if i and i:get_list("box") then - - local wagon_data = advtrains.wagons[v] - local wagon_fc - if wagon_data.fc then - if not wagon_data.fcind then wagon_data.fcind = 1 end - wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or "" - end - - if node_fc == "" or wagon_fc == node_fc then - if not unload then - for _, item in ipairs(inv:get_list("main")) do - if i:get_list("box") and i:room_for_item("box", item) then - i:add_item("box", item) - inv:remove_item("main", item) - end - end - else - for _, item in ipairs(i:get_list("box")) do - if inv:get_list("main") and inv:room_for_item("main", item) then - i:remove_item("box", item) - inv:add_item("main", item) - end - end - end - end - end - end - end -end - - - -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_unload", - texture_prefix="advtrains_dtrack_unload", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared_unload.png", - description=attrans("Unloading Track"), - formats={}, - get_additional_definiton = function(def, preset, suffix, rotation) - return { - after_dig_node=function(pos) - advtrains.invalidate_all_paths() - advtrains.ndb.clear(pos) - end, - on_rightclick = function(pos, node, player) - show_fc_formspec(pos, player) - end, - advtrains = { - on_train_enter = function(pos, train_id) - train_load(pos, train_id, true) - end, - }, - } - end - }, advtrains.trackpresets.t_30deg_straightonly) -advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_load", - texture_prefix="advtrains_dtrack_load", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared_load.png", - description=attrans("Loading Track"), - formats={}, - get_additional_definiton = function(def, preset, suffix, rotation) - return { - after_dig_node=function(pos) - advtrains.invalidate_all_paths() - advtrains.ndb.clear(pos) - end, - on_rightclick = function(pos, node, player) - show_fc_formspec(pos, player) - end, - advtrains = { - on_train_enter = function(pos, train_id) - train_load(pos, train_id, false) - end, - }, - } - end - }, advtrains.trackpresets.t_30deg_straightonly) - --- mod-dependent crafts -local loader_core = "default:mese_crystal" --fallback -if minetest.get_modpath("basic_materials") then - loader_core = "basic_materials:ic" -elseif minetest.get_modpath("technic") then - loader_core = "technic:control_logic_unit" -end ---print("Loader Core: "..loader_core) - -minetest.register_craft({ - type="shapeless", - output = 'advtrains:dtrack_load_placer', - recipe = { - "advtrains:dtrack_placer", - loader_core, - "default:chest" - }, -}) -loader_core = nil --nil the crafting variable - ---craft between load/unload tracks -minetest.register_craft({ - type="shapeless", - output = 'advtrains:dtrack_unload_placer', - recipe = { - "advtrains:dtrack_load_placer", - }, -}) -minetest.register_craft({ - type="shapeless", - output = 'advtrains:dtrack_load_placer', - recipe = { - "advtrains:dtrack_unload_placer", - }, -}) - - -if mesecon then - advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_detector_off", - texture_prefix="advtrains_dtrack_detector", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared_detector_off.png", - description=attrans("Detector Rail"), - formats={}, - get_additional_definiton = function(def, preset, suffix, rotation) - return { - mesecons = { - receptor = { - state = mesecon.state.off, - rules = advtrains.meseconrules - } - }, - advtrains = { - on_updated_from_nodedb = function(pos, node) - mesecon.receptor_off(pos, advtrains.meseconrules) - end, - on_train_enter=function(pos, train_id) - advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) - if advtrains.is_node_loaded(pos) then - mesecon.receptor_on(pos, advtrains.meseconrules) - end - end - } - } - end - }, advtrains.ap.t_30deg_straightonly) - advtrains.register_tracks("default", { - nodename_prefix="advtrains:dtrack_detector_on", - texture_prefix="advtrains_dtrack", - models_prefix="advtrains_dtrack", - models_suffix=".b3d", - shared_texture="advtrains_dtrack_shared_detector_on.png", - description="Detector(on)(you hacker you)", - formats={}, - get_additional_definiton = function(def, preset, suffix, rotation) - return { - mesecons = { - receptor = { - state = mesecon.state.on, - rules = advtrains.meseconrules - } - }, - advtrains = { - on_updated_from_nodedb = function(pos, node) - mesecon.receptor_on(pos, advtrains.meseconrules) - end, - on_train_leave=function(pos, train_id) - advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2}) - if advtrains.is_node_loaded(pos) then - mesecon.receptor_off(pos, advtrains.meseconrules) - end - end - } - } - end - }, advtrains.ap.t_30deg_straightonly_noplacer) -minetest.register_craft({ - type="shapeless", - output = 'advtrains:dtrack_detector_off_placer', - recipe = { - "advtrains:dtrack_placer", - "mesecons:wire_00000000_off" - }, -}) -end ---TODO legacy ---I know lbms are better for this purpose -for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="swrcr", }) do - minetest.register_abm({ - -- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_"..name}, - interval = 1.0, -- Operation interval in seconds - chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep, param2=node.param2}) end, - }) - minetest.register_abm({ - -- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_"..name.."_45"}, - interval = 1.0, -- Operation interval in seconds - chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep.."_45", param2=node.param2}) end, - }) -end - -if advtrains.register_replacement_lbms then -minetest.register_lbm({ - name = "advtrains:ramp_replacement_1", --- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_vert1"}, - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst1", param2=(node.param2+2)%4}) end, -}) -minetest.register_lbm({ - name = "advtrains:ramp_replacement_1", --- -- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_vert2"}, - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end, -}) - minetest.register_abm({ - name = "advtrains:st_rep_1", - -- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_st"}, - interval=1, - chance=1, - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st", param2=node.param2}) end, - }) - minetest.register_lbm({ - name = "advtrains:st_rep_1", - -- -- In the following two fields, also group:groupname will work. - nodenames = {"advtrains:track_st_45"}, - action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st_45", param2=node.param2}) end, - }) -end -- cgit v1.2.3 From ea074b2a3378c1b79d37d0dd94947ebbaf8ece32 Mon Sep 17 00:00:00 2001 From: orwell Date: Sun, 15 Oct 2023 16:40:10 +0200 Subject: Re-implement point origin handling (replace old points_split hack by proper solution) --- advtrains/init.lua | 2 +- advtrains/nodedb.lua | 2 +- advtrains/path.lua | 17 +++++++++++------ advtrains/trainlogic.lua | 48 ++++++++++++++++++++++++++++-------------------- 4 files changed, 41 insertions(+), 28 deletions(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 78126e5..a5f12f7 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -474,7 +474,7 @@ advtrains.avt_save = function(remove_players_from_wagons) "atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open", "text_outside", "text_inside", "line", "routingcode", "il_sections", "speed_restriction", "speed_restrictions_t", "is_shunt", - "points_split", "autocouple", "atc_wait_autocouple", "ars_disable", + "path_ori_cp", "autocouple", "atc_wait_autocouple", "ars_disable", }) --then save it tmp_trains[id]=v diff --git a/advtrains/nodedb.lua b/advtrains/nodedb.lua index d903be7..ff07df4 100644 --- a/advtrains/nodedb.lua +++ b/advtrains/nodedb.lua @@ -264,7 +264,7 @@ end --get_node with pseudoload. now we only need track data, so we can use the trackdb as second fallback --nothing new will be saved inside the trackdb. --returns: ---true, conn1, conn2, rely1, rely2, railheight in case everything's right. +--true, conns, railheight, connmap in case everything's right. --false if it's not a rail or the train does not drive on this rail, but it is loaded or --nil if the node is neither loaded nor in trackdb --the distraction between false and nil will be needed only in special cases.(train initpos) diff --git a/advtrains/path.lua b/advtrains/path.lua index 588140d..28df529 100644 --- a/advtrains/path.lua +++ b/advtrains/path.lua @@ -217,9 +217,8 @@ function advtrains.path_get(train, index) advtrains.occ.set_item(train.id, adj_pos, pef) local mconnid = advtrains.get_matching_conn(adj_connid, next_connmap) - -- If we have split points, notify accordingly - -- TODO readd support for split points (remember the cp and cn of points) - + -- NO split points handling here. It is only required for backwards path calculation + adj_pos.y = adj_pos.y + nextrail_y train.path_cp[pef] = adj_connid train.path_cn[pef] = mconnid @@ -253,9 +252,15 @@ function advtrains.path_get(train, index) advtrains.occ.set_item(train.id, adj_pos, peb) local mconnid = advtrains.get_matching_conn(adj_connid, next_connmap) - -- If we have split points, notify accordingly - -- TODO readd support for split points (remember the cp and cn of points) - + -- If, for this position, we have remembered the origin conn, apply it here + if next_connmap then -- only needs to be done when this track is a turnout (>2 conns) + local origin_conn = train.path_ori_cp[advtrains.encode_pos(adj_pos)] + if origin_conn then + atdebug("Train",train.id,"at",adj_pos,"restoring turnout origin CP",origin_conn,"for path item",index) + mconnid = origin_conn + end + end + adj_pos.y = adj_pos.y + nextrail_y train.path_cn[peb] = adj_connid train.path_cp[peb] = mconnid diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index c6762c9..cb1f9a6 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -280,8 +280,10 @@ function advtrains.train_ensure_init(id, train) assertdef(train, "velocity", 0) --assertdef(train, "tarvelocity", 0) assertdef(train, "acceleration", 0) - assertdef(train, "id", id) - + if train.id ~= id then + train.id = id + end + assertdef(train, "path_ori_cp", {}) if not train.max_speed then --atprint("in ensure_init: missing properties, updating!") @@ -861,13 +863,10 @@ local function tnc_call_enter_callback(pos, train_id, train, index) run_callbacks_enter_node(pos, train_id, train, index) -- check for split points - if mregnode and mregnode.at_conns and #mregnode.at_conns == 3 and train.path_cp[index] == 3 then - -- train came from connection 3 of a switch, so it split points. - if not train.points_split then - train.points_split = {} - end - train.points_split[advtrains.encode_pos(pos)] = true - --atdebug(train_id,"split points at",pos) + if mregnode and mregnode.at_conn_map then + -- If this node has >2 conns (and a connmap), remember the connection where we came from to handle split points + atdebug("Train",train_id,"at",pos,"saving turnout origin CP",train.path_cp[index],"for path item",index) + train.path_ori_cp[advtrains.encode_pos(pos)] = train.path_cp[index] end end local function tnc_call_leave_callback(pos, train_id, train, index) @@ -882,18 +881,11 @@ local function tnc_call_leave_callback(pos, train_id, train, index) run_callbacks_leave_node(pos, train_id, train, index) -- split points do not matter anymore. clear them - if train.points_split then - if train.points_split[advtrains.encode_pos(pos)] then - train.points_split[advtrains.encode_pos(pos)] = nil - --atdebug(train_id,"has passed split points at",pos) - end - -- any entries left? - for _,_ in pairs(train.points_split) do - return - end - train.points_split = nil + if mregnode and mregnode.at_conn_map then + -- If this node has >2 conns (and a connmap), remember the connection where we came from to handle split points + atdebug("Train",train_id,"at",pos,"removing turnout origin CP for path item",index," because train has left it") + train.path_ori_cp[advtrains.encode_pos(pos)] = nil end - -- WARNING possibly unreachable place! end function advtrains.tnc_call_approach_callback(pos, train_id, train, index, lzbdata) @@ -1189,8 +1181,24 @@ function advtrains.invert_train(train_id) return end + -- Before flipping the train, we must check if there are any points on the path + -- which will become split on rotating, and store their cn (which will become the cp) + local ori_cp_after_flip = {} + for index = atround(train.end_index),atround(train.index) do + local pos = advtrains.path_get(train, index) + local ok, conns, railheight, connmap = advtrains.get_rail_info_at(pos) + if ok and connmap then + atdebug("Reversing Train",train.id," ori_cp Checks: at",pos,"saving turnout origin CP",train.path_cn[index],"for path item",index) + ori_cp_after_flip[advtrains.encode_pos(pos)] = train.path_cn[index] + end + end + + -- Actual rotation happens here! This sets the path restore position to the end of the train, inverting the connid. advtrains.path_setrestore(train, true) + -- clear the origin cp list because it is now invalid, and replace it by what we built prior. + train.path_ori_cp = ori_cp_after_flip + -- rotate some other stuff if train.door_open then train.door_open = - train.door_open -- cgit v1.2.3 From 9fac1db45f79e2312415500b6ec9d22a8edb0cdd Mon Sep 17 00:00:00 2001 From: orwell Date: Wed, 20 Dec 2023 00:20:56 +0100 Subject: Set maximum train length and prevent coupling if it would exceed --- advtrains/couple.lua | 7 +++++++ advtrains/init.lua | 3 +++ 2 files changed, 10 insertions(+) (limited to 'advtrains/init.lua') diff --git a/advtrains/couple.lua b/advtrains/couple.lua index 1318c12..b6a445e 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -227,6 +227,13 @@ function advtrains.couple_trains(init_train, invert_init_train, stat_train, stat local stp = stat_train.trainparts local stat_wagoncnt = #stp local stat_trainlen = stat_train.trainlen -- save the train length of stat train, to be added to index + + -- sanity check, prevent coupling if train would be longer than 20 after coupling + local tot_len = init_wagoncnt + stat_wagoncnt + if tot_len > advtrains.TRAIN_MAX_WAGONS then + atwarn("Cannot couple",stat_train.id,"and",init_train.id,"- train would have length",tot_len,"which is above the limit of",advtrains.TRAIN_MAX_WAGONS) + return + end if stat_train_opposite then -- insert wagons in inverse order and set their wagon_flipped state diff --git a/advtrains/init.lua b/advtrains/init.lua index a7e5764..9c977eb 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -48,6 +48,9 @@ advtrains.IGNORE_WORLD = false local NO_SAVE = false -- Do not save any data to advtrains save files +advtrains.TRAIN_MAX_WAGONS = 20 +-- Limit on the maximum number of wagons that may be in a train + -- ========================================================================== -- Use a global slowdown factor to slow down train movements. Now a setting -- cgit v1.2.3 From 2ea4a8cff1d8e335fda472e4c7988424ca522610 Mon Sep 17 00:00:00 2001 From: orwell Date: Tue, 6 Feb 2024 23:06:38 +0100 Subject: Add chatcommand and luaatc function to get global_slowdown --- advtrains/init.lua | 10 ++++++++++ advtrains_luaautomation/environment.lua | 3 +++ 2 files changed, 13 insertions(+) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 9c977eb..cc8f8d1 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -758,6 +758,16 @@ minetest.register_chatcommand("at_disable_step", end, }) +minetest.register_chatcommand("at_status", + { + params = "", + description = "Print advtrains status info", + privs = {train_operator = true}, + func = function(name, param) + return true, advtrains.print_concat_table({"Advtrains Status: no_action",no_action,"slowdown",advtrains.global_slowdown,"(log",math.log(advtrains.global_slowdown),")"}) + end, +}) + advtrains.is_no_action = function() return no_action end diff --git a/advtrains_luaautomation/environment.lua b/advtrains_luaautomation/environment.lua index d85bedc..9fcba1d 100644 --- a/advtrains_luaautomation/environment.lua +++ b/advtrains_luaautomation/environment.lua @@ -164,6 +164,9 @@ local static_env = { return false end end, + get_slowdown = function() + return advtrains.global_slowdown + end } -- If interlocking is present, enable route setting functions -- cgit v1.2.3 From c145e5db7473a0baab6438d7c2ed9616948d8387 Mon Sep 17 00:00:00 2001 From: orwell Date: Sat, 22 Jun 2024 21:11:50 +0200 Subject: SmartRoute: Implement auto route search and first prototype --- advtrains/init.lua | 2 +- advtrains_interlocking/init.lua | 1 + advtrains_interlocking/route_ui.lua | 8 ++ advtrains_interlocking/signal_aspect_ui.lua | 1 + advtrains_interlocking/smartroute.lua | 149 ++++++++++++++++++++++++++++ advtrains_interlocking/tcb_ts_ui.lua | 3 + 6 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 advtrains_interlocking/smartroute.lua (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 3bd8374..bca39df 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -33,7 +33,7 @@ advtrains = {trains={}, player_to_train_mapping={}} -- =======================Development/debugging settings===================== -- DO NOT USE FOR NORMAL OPERATION -local DUMP_DEBUG_SAVE = false +local DUMP_DEBUG_SAVE = true -- dump the save files in human-readable format into advtrains_DUMP local GENERATE_ATRICIFIAL_LAG = false diff --git a/advtrains_interlocking/init.lua b/advtrains_interlocking/init.lua index a4ddbad..5883ab3 100644 --- a/advtrains_interlocking/init.lua +++ b/advtrains_interlocking/init.lua @@ -22,6 +22,7 @@ dofile(modpath.."route_prog.lua") dofile(modpath.."routesetting.lua") dofile(modpath.."tcb_ts_ui.lua") dofile(modpath.."route_ui.lua") +dofile(modpath.."smartroute.lua") dofile(modpath.."tool.lua") dofile(modpath.."approach.lua") diff --git a/advtrains_interlocking/route_ui.lua b/advtrains_interlocking/route_ui.lua index 982c579..863fe11 100644 --- a/advtrains_interlocking/route_ui.lua +++ b/advtrains_interlocking/route_ui.lua @@ -86,6 +86,9 @@ function atil.show_route_edit_form(pname, sigd, routeid) form = form.."textlist[0.5,2;3,3.9;rtelog;"..table.concat(tab, ",").."]" form = form.."button[0.5,6;3,1;back;<<< Back to signal]" + if route.smartroute_generated then + form = form.."button[3.5,6;2,1;noautogen;Clr Autogen]" + end form = form.."button[5.5,6;3,1;delete;Delete Route]" --atdebug(route.ars) @@ -135,6 +138,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) advtrains.interlocking.show_signal_aspect_selector(pname, suppasp, route.name, callback, route.aspect or advtrains.interlocking.GENERIC_FREE) return end + + if fields.noautogen then + route.smartroute_generated = nil + end + if fields.delete then -- if something set the route in the meantime, make sure this doesn't break. atil.route.update_route(sigd, tcbs, nil, true) diff --git a/advtrains_interlocking/signal_aspect_ui.lua b/advtrains_interlocking/signal_aspect_ui.lua index 892c53b..39aab17 100644 --- a/advtrains_interlocking/signal_aspect_ui.lua +++ b/advtrains_interlocking/signal_aspect_ui.lua @@ -83,6 +83,7 @@ function advtrains.interlocking.show_ip_sa_form(pos, pname) -- Create Signal aspect formspec elements local ndef = advtrains.ndb.get_ndef(pos) if ndef and ndef.advtrains then + form[#form+1] = F.label(0.5, 2, "Signal Aspect:") -- main aspect list if ndef.advtrains.main_aspects then local entries = { "" } diff --git a/advtrains_interlocking/smartroute.lua b/advtrains_interlocking/smartroute.lua new file mode 100644 index 0000000..770c379 --- /dev/null +++ b/advtrains_interlocking/smartroute.lua @@ -0,0 +1,149 @@ +-- smartroute.lua +-- Implementation of the advtrains auto-route search + +local atil = advtrains.interlocking +local ildb = atil.db +local sr = {} + + +local function otherside(s) + if s==1 then return 2 else return 1 end +end + +--route search implementation +-- Note this is similar to recursively_find_routes in database.lua, there used for the rscache + +local function recursively_find_routes(s_pos, s_connid, searching_shunt, tcbseq, mark_pos, result_table, scan_limit) + --atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit) + local ti = advtrains.get_track_iterator(s_pos, s_connid, scan_limit, false) + local pos, connid, bconnid = ti:next_branch() + pos, connid, bconnid = ti:next_track()-- step once to get ahead of previous turnout + local last_pos + repeat + -- record position in mark_pos + local pts = advtrains.encode_pos(pos) + mark_pos[pts] = true + + local node = advtrains.ndb.get_node_or_nil(pos) + atdebug("(SmartRoute) Walk ",pos, "nodename", node.name, "entering at conn",bconnid) + local ndef = minetest.registered_nodes[node.name] + if ndef.advtrains and ndef.advtrains.node_state_map then + -- Stop, this is a switchable node. Find out which conns we can go at + atdebug("(SmartRoute) Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid) + local out_conns = ildb.get_possible_out_connids(node.name, bconnid) + for oconnid, state in pairs(out_conns) do + --atdebug("Going in direction",oconnid,"state",state) + recursively_find_routes(pos, oconnid, searching_shunt, table.copy(tcbseq), table.copy(mark_pos), result_table, ti.limit) + end + return + end + --otherwise, this might be a tcb + local tcb = ildb.get_tcb(pos) + if tcb then + local fsigd = { p = pos, s = connid } + atdebug("(SmartRoute) Encounter TCB ",fsigd) + tcbseq[#tcbseq+1] = fsigd + -- check if this is a possible route endpoint + local tcbs = tcb[connid] + if tcbs.signal then + local ndef = advtrains.ndb.get_ndef(tcbs.signal) + if ndef and ndef.advtrains then + if ndef.advtrains.route_role == "main" or ndef.advtrains.route_role == "main_distant" + or ndef.advtrains.route_role == "end" or ndef.advtrains.route_role == "shunt" then + -- signal is suitable target + local is_mainsignal = ndef.advtrains.route_role ~= "shunt" + -- record the found route in the results + result_table[#result_table+1] = { + tcbseq = table.copy(tcbseq), + mark_pos = table.copy(mark_pos), + shunt_route = not is_mainsignal, + to_end_of_track = false, + name = tcbs.signal_name or atil.sigd_to_string(fsigd) + } + -- if this is a main signal and/or we are only searching shunt routes, stop the search here + if is_mainsignal or searching_shunt then + atdebug("(SmartRoute) Terminating here because it is main or only shunt routes searched") + return + end + end + end + end + end + -- Go forward + last_pos = pos + pos, connid, bconnid = ti:next_track() + until not pos -- this stops the loop when either the track end is reached or the limit is hit + --atdebug("recursively_find_routes: Reached track end or limit at", last_pos, ". This path is not saved, returning") +end + +local function build_route_from_foundroute(froute, name) + local route = { + name = froute.name, + use_rscache = true, + smartroute_generated = true, + } + for _, sigd in ipairs(froute.tcbseq) do + route[#route+1] = { next = sigd, locks = {} } + end + return route +end + +-- Maximum scan length for track iterator +local TS_MAX_SCAN = 1000 + +function sr.init(pname, sigd) + -- is start signal a shunt signal? + local is_startsignal_shunt = false + local tcbs = ildb.get_tcbs(sigd) + if tcbs.signal then + local ndef = advtrains.ndb.get_ndef(tcbs.signal) + if ndef and ndef.advtrains then + if ndef.advtrains.route_role == "shunt" then + is_startsignal_shunt = true + end + end + end + local result_table = {} + recursively_find_routes(sigd.p, sigd.s, is_startsignal_shunt, {}, {}, result_table, TS_MAX_SCAN) + + atdebug("Smartroute search finished:",result_table) + + -- Short-circuit logic right now for testing + -- go through and delete all routes that are autogenerated + local i = 1 + while i<=#tcbs.routes do + if tcbs.routes[i].smartroute_generated then + table.remove(tcbs.routes, i) + else + i=i+1 + end + end + -- just plainly create routes! + for idx, froute in ipairs(result_table) do + tcbs.routes[#tcbs.routes+1] = build_route_from_foundroute(froute) + end + atwarn("Smartroute done!") +end + + + +--[[ + player1 = { + origin = + found_routes = { + { tcbseq = {, , }, mark_pos = { table with keys being encoded_pos of rails constituting route }, to_end_of_track = false, shunt_route = false } + } + } +]]-- +local player_smartroute = {} + +minetest.register_on_punchnode(function(pos, node, player, pointed_thing) + local pname = player:get_player_name() + if not minetest.check_player_privs(pname, "interlocking") then + return + end + -- TODO +end) + + +advtrains.interlocking.smartroute = sr diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index bdb0a18..7f75bb9 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -616,6 +616,9 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle local strtab = {} for idx, route in ipairs(tcbs.routes) do local clr = "" + if route.smartroute_generated then + clr = "#FFFF55" + end if route.ars then clr = "#FF5555" if route.ars.default then -- cgit v1.2.3 From 0bfc7bbe099c7bba20cf1194b3ffad9471d0c7a4 Mon Sep 17 00:00:00 2001 From: "Y. Wang" Date: Fri, 2 Jun 2023 13:30:54 +0200 Subject: Rework graphical train HUD code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - A basic texture manipulation API is added; currently this is only a (selected) subset of texture modifiers provided by MT; the goal is to avoid writing (potentially incorrect) texture strings by hand; - The graphical HUD code is cleaned up; in particular, most code used for generating texture patterns are moved to texture.lua so that the code can be used outside of the HUD; - Inactive elements are given the darkslategray background. A basic unittest is added; however, it needs to be expanded for better coverage. Reported-by: Lars Müller --- advtrains/init.lua | 1 + advtrains/spec/texture_spec.lua | 19 ++++ advtrains/texture.lua | 228 ++++++++++++++++++++++++++++++++++++++++ advtrains/trainhud.lua | 120 ++++++--------------- 4 files changed, 281 insertions(+), 87 deletions(-) create mode 100644 advtrains/spec/texture_spec.lua create mode 100644 advtrains/texture.lua (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index cc8f8d1..33e5b1d 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -202,6 +202,7 @@ advtrains.meseconrules = advtrains.fpath=minetest.get_worldpath().."/advtrains" advtrains.speed = dofile(advtrains.modpath.."/speed.lua") +advtrains.texture = dofile(advtrains.modpath.."/texture.lua") dofile(advtrains.modpath.."/path.lua") dofile(advtrains.modpath.."/trainlogic.lua") diff --git a/advtrains/spec/texture_spec.lua b/advtrains/spec/texture_spec.lua new file mode 100644 index 0000000..2e3bd5d --- /dev/null +++ b/advtrains/spec/texture_spec.lua @@ -0,0 +1,19 @@ +package.path = "../?.lua;" .. package.path +local T = require "texture" + +describe("Texture creation", function() + it("works", function() + assert.same("^.png", tostring(T.raw"^.png")) + assert.same("foo\\:bar.png", tostring(T"foo:bar.png")) + end) +end) + +describe("Texture modifiers", function() + it("work", function() + assert.same("x^[colorize:c", tostring(T"x":colorize"c")) + assert.same("x^[colorize:c:alpha", tostring(T"x":colorize("c", "alpha"))) + assert.same("x^[multiply:c", tostring(T"x":multiply"c")) + assert.same("x^[resize:2x3", tostring(T"x":resize(2, 3))) + assert.same("x^[transformI", tostring(T"x":transform"I")) + end) +end) diff --git a/advtrains/texture.lua b/advtrains/texture.lua new file mode 100644 index 0000000..1ecc91b --- /dev/null +++ b/advtrains/texture.lua @@ -0,0 +1,228 @@ +local tx = {} +setmetatable(tx, {__call = function(_, ...) return tx.base(...) end}) + +function tx.escape(str) + return (string.gsub(tostring(str), [[([%^:\])]], [[\%1]])) +end + +local function getargs(...) + return select("#", ...), {...} +end + +local function curry(f, x) + return function(...) + return f(x, ...) + end +end + +local function xmkmodifier(func) + return function(self, ...) + table.insert(self, (func(...))) + return self + end +end + +local function mkmodifier(fmt, spec) + return xmkmodifier(function(...) + local count = select("#", ...) + local args = {...} + for k, f in pairs(spec) do + args[k] = f(args[k]) + end + return string.format(fmt, unpack(args, 1, count)) + end) +end + +-- Texture object +local tx_lib = {} +local tx_mt = { + __index = tx_lib, + __tostring = function(self) + return table.concat(self, "^") + end, + __concat = function(a, b) + return tx.raw(("%s^%s"):format(tostring(a), tostring(b))) + end, +} + +function tx.raw(str) + return setmetatable({str}, tx_mt) +end +function tx.base(str) + return tx.raw(tx.escape(str)) +end +-- TODO: use [fill when 5.8.0 becomes widely used client-side +function tx.fill(w, h, color) + return tx"advtrains_hud_bg.png":resize(w, h):colorize(color) +end + +-- Most texture modifiers +tx_lib.colorize = xmkmodifier(function(c, a) + local str = ("[colorize:%s"):format(tx.escape(c)) + if a then + str = str .. ":" .. a + end + return str +end) +tx_lib.multiply = mkmodifier("[multiply:%s", {tx.escape}) +tx_lib.resize = mkmodifier("[resize:%dx%d", {}) +tx_lib.transform = mkmodifier("[transform%s", {tx.escape}) + +-- [combine + +local combine = {} + +function combine:add(x, y, ent) + table.insert(self.st, ([[%d,%d=%s]]):format(x, y, tx.escape(tostring(ent)))) + return self +end + +local combine_mt = { + __index = combine, + __tostring = function(self) + return table.concat(self.st, ":") + end, +} + +function tx.combine(w, h, bg) + local base = ("[combine:%dx%d"):format(w, h) + local obj = setmetatable({width = w, height = h, st = {base}}, combine_mt) + if bg then + obj:add_fill(0, 0, w, h, bg) + end + return obj +end + +function combine:add_fill(x, y, ...) + return self:add(x, y, tx.fill(...)) +end + +local function add_multicolor_fill(n, self, x, y, w, h, ...) + local argc, argv = getargs(...) + local t = 0 + for k = 1, argc, 2 do + t = t + argv[k] + end + local newargs = {x, y, w, h} + local sk, wk = n, n+2 + local s = newargs[wk]/t + for k = 1, argc, 2 do + local v = argv[k] * s + newargs[wk] = v + newargs[5] = argv[k+1] + self:add_fill(unpack(newargs)) + newargs[sk] = newargs[sk] + v + end + return self +end +combine.add_multicolor_fill_topdown = curry(add_multicolor_fill, 2) +combine.add_multicolor_fill_leftright = curry(add_multicolor_fill, 1) + +local function add_segmentbar(n, self, x, y, w, h, m, c, ...) + local argc, argv = getargs(...) + local baseargs = {x, y, w, h} + local ss = (baseargs[n+2]+m)/c + local bs = ss - m + for k = 1, argc, 3 do + local lower, upper, fill = argv[k], argv[k+1], argv[k+2] + lower = math.max(0, math.floor(lower)+1) + upper = math.min(c, math.floor(upper)) + if lower < upper then + local args = {x, y, w, h, fill} + args[n+2] = bs + args[n] = args[n] + ss*lower + for i = lower, upper do + self:add_fill(unpack(args)) + args[n] = args[n] + ss + end + end + end + return self +end +combine.add_segmentbar_topdown = curry(add_segmentbar, 2) +combine.add_segmentbar_leftright = curry(add_segmentbar, 1) + +local function add_lever(n, self, x, y, w, h, hs, ss, val, hf, sf) + local baseargs = {x, y, w, h} + local sargs = {x, y, w, h, sf} + sargs[5-n] = ss + sargs[n+2] = baseargs[n+2] + ss - hs + for k = 1, 2 do + sargs[k] = baseargs[k] + (baseargs[k+2] - sargs[k+2])/2 + end + self:add_fill(unpack(sargs)) + local hargs = {x, y, w, h, hf} + hargs[n+2] = hs + hargs[n] = baseargs[n] + (baseargs[n+2]-hs)*val + self:add_fill(unpack(hargs)) + return self +end +combine.add_lever_topdown = curry(add_lever, 2) +combine.add_lever_leftright = curry(add_lever, 1) + +--[[ Seven-segment display + -1- +6 2 + -7- +5 3 + -4- +--]] +local sevenseg_digits = { + ["0"] = {1, 2, 3, 4, 5, 6}, + ["1"] = {2, 3}, + ["2"] = {1, 2, 4, 5, 7}, + ["3"] = {1, 2, 3, 4, 7}, + ["4"] = {2, 3, 6, 7}, + ["5"] = {1, 3, 4, 6, 7}, + ["6"] = {1, 3, 4, 5, 6, 7}, + ["7"] = {1, 2, 3}, + ["8"] = {1, 2, 3, 4, 5, 6, 7}, + ["9"] = {1, 2, 3, 4, 6, 7}, +} + +function combine:add_str7seg(x0, y0, tw, th, str, fill) + --[[ w and h (as width/height of individual (horizontal) segments) have the following properties: + tw = n(w+3h)-h + th = 2w+3h + --]] + local len = #str + local h = (2*tw-len*th)/(3*len-2) + local w = (th-3*h)/2 + local ws = w+3*h + local segs = { + {h, 0, w, h}, + {w+h, h, h, w}, + {w+h, w+2*h, h, w}, + {h, 2*(w+h), w, h}, + {0, w+2*h, h, w}, + {0, h, h, w}, + {h, w+h, w, h}, + } + for i = 1, len do + for _, k in pairs(sevenseg_digits[string.sub(str, i, i)] or {}) do + local s = segs[k] + self:add_fill(s[1]+x0, s[2]+y0, s[3], s[4], fill) + end + x0 = x0 + ws + end + return self +end + +function combine:add_n7seg(x, y, w, h, n, prec, ...) + if not (type(n) == "number" and type(prec) == "number") then + error("passed non-numeric value or precision to numeric display") + elseif prec < 0 then + error("negative length") + end + local pfx = "" + if n >= 0 then + n = math.min(10^prec-1, n) + else + n = math.min(10^(prec-1)-1, -n) + pfx = "-" + end + local str = ("%d"):format(n) + return self:add_str7seg(x, y, w, h, pfx .. ("0"):rep(prec-#str-#pfx) .. str, ...) +end + +return tx diff --git a/advtrains/trainhud.lua b/advtrains/trainhud.lua index 22aa6cf..b8eb512 100644 --- a/advtrains/trainhud.lua +++ b/advtrains/trainhud.lua @@ -1,5 +1,7 @@ --trainhud.lua: holds all the code for train controlling +local T = advtrains.texture + advtrains.hud = {} advtrains.hhud = {} @@ -184,98 +186,41 @@ function advtrains.hud_train_format(train, flip) local vel = advtrains.abs_ceil(train.velocity) local vel_kmh=advtrains.abs_ceil(advtrains.ms_to_kmh(train.velocity)) - local tlev=train.lever or 1 + local tlev=train.lever or 3 if train.velocity==0 and not train.active_control then tlev=1 end if train.hud_lzb_effect_tmr then tlev=1 end - local ht = {"[combine:440x110:0,0=(advtrains_hud_bg.png^[resize\\:440x110)"} + local hud = T.combine(440, 110, "black") local st = {} if train.debug then st = {train.debug} end - -- seven-segment display - local function sevenseg(digit, x, y, w, h, m) - --[[ - -1- - 2 3 - -4- - 5 6 - -7- - ]] - local segs = { - {h, 0, w, h}, - {0, h, h, w}, - {w+h, h, h, w}, - {h, w+h, w, h}, - {0, w+2*h, h, w}, - {w+h, w+2*h, h, w}, - {h, 2*(w+h), w, h}} - local trans = { - [0] = {true, true, true, false, true, true, true}, - [1] = {false, false, true, false, false, true, false}, - [2] = {true, false, true, true, true, false, true}, - [3] = {true, false, true, true, false, true, true}, - [4] = {false, true, true, true, false, true, false}, - [5] = {true, true, false, true, false, true, true}, - [6] = {true, true, false, true, true, true, true}, - [7] = {true, false, true, false, false, true, false}, - [8] = {true, true, true, true, true, true, true}, - [9] = {true, true, true, true, false, true, true}} - local ent = trans[digit or 10] - if not ent then return end - for i = 1, 7, 1 do - if ent[i] then - local s = segs[i] - ht[#ht+1] = sformat("%d,%d=(advtrains_hud_bg.png^[resize\\:%dx%d^%s)",x+s[1], y+s[2], s[3], s[4], m) - end - end - end - -- lever - ht[#ht+1] = "275,10=(advtrains_hud_bg.png^[colorize\\:cyan^[resize\\:5x18)" - ht[#ht+1] = "275,28=(advtrains_hud_bg.png^[colorize\\:white^[resize\\:5x18)" - ht[#ht+1] = "275,46=(advtrains_hud_bg.png^[colorize\\:orange^[resize\\:5x36)" - ht[#ht+1] = "275,82=(advtrains_hud_bg.png^[colorize\\:red^[resize\\:5x18)" - ht[#ht+1] = "292,16=(advtrains_hud_bg.png^[colorize\\:darkslategray^[resize\\:6x78)" - ht[#ht+1] = sformat("280,%s=(advtrains_hud_bg.png^[colorize\\:gray^[resize\\:30x18)",18*(4-tlev)+10) + hud:add_multicolor_fill_topdown(275, 10, 5, 90, 1, "cyan", 1, "white", 2, "orange", 1, "red") + hud:add_lever_topdown(280, 10, 30, 90, 18, 6, (4-tlev)/4, "gray", "darkslategray") -- reverser - ht[#ht+1] = sformat("245,10=(advtrains_hud_arrow.png^[transformFY%s)", flip and "" or "^[multiply\\:cyan") - ht[#ht+1] = sformat("245,85=(advtrains_hud_arrow.png%s)", flip and "^[multiply\\:orange" or "") - ht[#ht+1] = "250,35=(advtrains_hud_bg.png^[colorize\\:darkslategray^[resize\\:5x40)" - ht[#ht+1] = sformat("240,%s=(advtrains_hud_bg.png^[resize\\:25x15^[colorize\\:gray)", flip and 65 or 30) + hud:add(245, 10, T"advtrains_hud_arrow.png":transform"FY":multiply(flip and "gray" or "cyan")) + hud:add(245, 85, T"advtrains_hud_arrow.png":multiply(flip and "orange" or "gray")) + hud:add_lever_topdown(240, 30, 25, 50, 15, 5, flip and 1 or 0, "gray", "darkslategray") -- train control/safety indication - if train.tarvelocity or train.atc_command then - ht[#ht+1] = "10,10=(advtrains_hud_atc.png^[resize\\:30x30^[multiply\\:cyan)" - end - if train.hud_lzb_effect_tmr then - ht[#ht+1] = "50,10=(advtrains_hud_lzb.png^[resize\\:30x30^[multiply\\:red)" - end - if train.is_shunt then - ht[#ht+1] = "90,10=(advtrains_hud_shunt.png^[resize\\:30x30^[multiply\\:orange)" - end + hud:add(10, 10, T"advtrains_hud_atc.png":resize(30, 30):multiply((train.tarvelocity or train.atc_command) and "cyan" or "darkslategray")) + hud:add(50, 10, T"advtrains_hud_lzb.png":resize(30, 30):multiply(train.hud_lzb_effect_tmr and "red" or "darkslategray")) + hud:add(90, 10, T"advtrains_hud_shunt.png":resize(30, 30):multiply(train.is_shunt and "orange" or "darkslategray")) -- door - ht[#ht+1] = "187,10=(advtrains_hud_bg.png^[resize\\:26x30^[colorize\\:white)" - ht[#ht+1] = "189,12=(advtrains_hud_bg.png^[resize\\:22x11)" - ht[#ht+1] = sformat("170,10=(advtrains_hud_bg.png^[resize\\:15x30^[colorize\\:%s)", train.door_open==-1 and "white" or "darkslategray") - ht[#ht+1] = "172,12=(advtrains_hud_bg.png^[resize\\:11x11)" - ht[#ht+1] = sformat("215,10=(advtrains_hud_bg.png^[resize\\:15x30^[colorize\\:%s)", train.door_open==1 and "white" or "darkslategray") - ht[#ht+1] = "217,12=(advtrains_hud_bg.png^[resize\\:11x11)" + hud:add_fill(187, 10, 26, 30, "white"):add_fill(189, 12, 22, 11, "black") + hud:add_fill(170, 10, 15, 30, train.door_open==-1 and "white" or "darkslategray"):add_fill(172, 12, 11, 11, "black") + hud:add_fill(215, 10, 15, 30, train.door_open==1 and "white" or "darkslategray"):add_fill(217, 12, 11, 11, "black") -- speed indication(s) - sevenseg(math.floor(vel/10), 320, 10, 30, 10, "[colorize\\:red\\:255") - sevenseg(vel%10, 380, 10, 30, 10, "[colorize\\:red\\:255") - for i = 1, vel, 1 do - ht[#ht+1] = sformat("%d,65=(advtrains_hud_bg.png^[resize\\:8x20^[colorize\\:white)", i*11-1) - end - for i = max+1, 20, 1 do - ht[#ht+1] = sformat("%d,65=(advtrains_hud_bg.png^[resize\\:8x20^[colorize\\:darkslategray)", i*11-1) - end + hud:add_n7seg(320, 10, 110, 90, vel, 2, "red") + hud:add_segmentbar_leftright(10, 65, 217, 20, 3, 20, max, 20, "darkslategray", 0, vel, "white") if res and res > 0 then - ht[#ht+1] = sformat("%d,60=(advtrains_hud_bg.png^[resize\\:3x30^[colorize\\:red\\:255)", 7+res*11) + hud:add_fill(7+res*11, 60, 3, 30, "red") end if train.tarvelocity then - ht[#ht+1] = sformat("%d,85=(advtrains_hud_arrow.png^[multiply\\:cyan^[transformFY^[makealpha\\:#000000)", 1+train.tarvelocity*11) + hud:add(1+train.tarvelocity*11, 85, T"advtrains_hud_arrow.png":transform"FY":multiply"cyan") end + local lzbdisp local lzb = train.lzb if lzb and lzb.checkpoints then local oc = lzb.checkpoints @@ -285,37 +230,38 @@ function advtrains.hud_train_format(train, flip) if spd == -1 then spd = nil end local c = not spd and "lime" or (type(spd) == "number" and (spd == 0) and "red" or "orange") or nil if c then - ht[#ht+1] = sformat("130,10=(advtrains_hud_bg.png^[resize\\:30x5^[colorize\\:%s)",c) - ht[#ht+1] = sformat("130,35=(advtrains_hud_bg.png^[resize\\:30x5^[colorize\\:%s)",c) if spd and spd~=0 then - ht[#ht+1] = sformat("%d,50=(advtrains_hud_arrow.png^[multiply\\:red^[makealpha\\:#000000)", 1+spd*11) + hud:add(1+spd*11, 50, T"advtrains_hud_arrow.png":multiply"red") end - local floor = math.floor - local dist = floor(((oc[i].index or train.index)-train.index)) + local dist = math.floor(((oc[i].index or train.index)-train.index)) dist = math.max(0, math.min(999, dist)) - for j = 1, 3, 1 do - sevenseg(floor((dist/10^(3-j))%10), 119+j*11, 18, 4, 2, "[colorize\\:"..c) - end + lzbdisp = {c = c, d = dist} break end end end + if not lzbdisp then + lzbdisp = {c = "darkslategray", d = 888} + end + hud:add_fill(130, 10, 30, 5, lzbdisp.c) + hud:add_fill(130, 35, 30, 5, lzbdisp.c) + hud:add_n7seg(131, 18, 28, 14, lzbdisp.d, 3, lzbdisp.c) if res and res == 0 then - st[#st+1] = attrans("OVERRUN RED SIGNAL! Examine situation and reverse train to move again.") + table.insert(st, attrans("OVERRUN RED SIGNAL! Examine situation and reverse train to move again.")) end if train.atc_command then - st[#st+1] = sformat("ATC: %s%s", train.atc_delay and advtrains.abs_ceil(train.atc_delay).."s " or "", train.atc_command or "") + table.insert(st, ("ATC: %s%s"):format(train.atc_delay and advtrains.abs_ceil(train.atc_delay).."s " or "", train.atc_command or "")) end - return table.concat(st,"\n"), table.concat(ht,":") + return table.concat(st,"\n"), tostring(hud) end local _, texture = advtrains.hud_train_format { -- dummy train object to demonstrate the train hud max_speed = 15, speed_restriction = 15, velocity = 15, tarvelocity = 12, active_control = true, lever = 3, ctrl = {lzb = true}, is_shunt = true, - door_open = 1, lzb = {oncoming = {{spd=6, idx=125.7}}}, index = 0, + door_open = 1, lzb = {checkpoints = {{speed=6, index=125.7}}}, index = 100, } minetest.register_node("advtrains:hud_demo",{ -- cgit v1.2.3 From 45e5ad3b378b17be7e0ce314ba964e01792d673d Mon Sep 17 00:00:00 2001 From: gpcf Date: Thu, 8 Aug 2024 23:53:29 +0200 Subject: Fix boardcom train id display, add command to teleport to train by id --- advtrains/init.lua | 15 +++++++++++++++ advtrains/wagons.lua | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 33e5b1d..f7d3b13 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -738,6 +738,21 @@ minetest.register_chatcommand("at_whereis", end end, }) +minetest.register_chatcommand("at_tp", + { + params = "", + description = "Teleports you to the position of the train with the given id", + privs = {train_operator = true, teleport = true}, + func = function(name,param) + local train = advtrains.trains[param] + if not train or not train.last_pos then + return false, "Train "..param.." does not exist or is invalid" + else + minetest.get_player_by_name(name):set_pos(train.last_pos) + return true, "Teleporting to train "..param + end + end, +}) minetest.register_chatcommand("at_disable_step", { params = "", diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index 730c623..677014a 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -970,7 +970,7 @@ function wagon:show_bordcom(pname) local data = advtrains.wagons[self.id] local linhei - local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1 | "..attrans("Train ID")..": "..(minetest.formspec_escape(self.id or "")).."]" + local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1 | "..attrans("Train ID")..": "..(minetest.formspec_escape(train.id or "")).."]" form=form.."textarea[0.5,1.5;7,1;text_outside;"..attrans("Text displayed outside on train")..";"..(minetest.formspec_escape(train.text_outside or "")).."]" form=form.."textarea[0.5,3;7,1;text_inside;"..attrans("Text displayed inside train")..";"..(minetest.formspec_escape(train.text_inside or "")).."]" form=form.."field[7.5,1.75;3,1;line;"..attrans("Line")..";"..(minetest.formspec_escape(train.line or "")).."]" -- cgit v1.2.3 From 9d7cec6151c0a9eca2454e9d6c85bc5596c5e946 Mon Sep 17 00:00:00 2001 From: Maverick2797 Date: Fri, 9 Aug 2024 19:47:27 +0800 Subject: Add Wagon Properties Tool Also added the Wagon ID to the Wagon Properties formspec --- advtrains/init.lua | 1 + advtrains/textures/advtrains_wagon_prop_tool.png | Bin 0 -> 779 bytes advtrains/wagonprop_tool.lua | 43 +++++++++++++++++++++++ advtrains/wagons.lua | 1 + 4 files changed, 45 insertions(+) create mode 100644 advtrains/textures/advtrains_wagon_prop_tool.png create mode 100644 advtrains/wagonprop_tool.lua (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index f7d3b13..06e456f 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -209,6 +209,7 @@ dofile(advtrains.modpath.."/trainlogic.lua") dofile(advtrains.modpath.."/trainhud.lua") dofile(advtrains.modpath.."/trackplacer.lua") dofile(advtrains.modpath.."/copytool.lua") +dofile(advtrains.modpath.."/wagonprop_tool.lua") dofile(advtrains.modpath.."/tracks.lua") dofile(advtrains.modpath.."/occupation.lua") dofile(advtrains.modpath.."/atc.lua") diff --git a/advtrains/textures/advtrains_wagon_prop_tool.png b/advtrains/textures/advtrains_wagon_prop_tool.png new file mode 100644 index 0000000..6352c55 Binary files /dev/null and b/advtrains/textures/advtrains_wagon_prop_tool.png differ diff --git a/advtrains/wagonprop_tool.lua b/advtrains/wagonprop_tool.lua new file mode 100644 index 0000000..2a4a9e2 --- /dev/null +++ b/advtrains/wagonprop_tool.lua @@ -0,0 +1,43 @@ +minetest.register_craftitem("advtrains:wagon_prop_tool",{ --craftitem because it does nothing on its own + description = attrans("Wagon Properties Tool\nPunch a wagon to view and edit the Wagon Properties"), + short_description = attrans("Wagon Properties Tool"), + groups = {}, + inventory_image = "advtrains_wagon_prop_tool.png", + wield_image = "advtrains_wagon_prop_tool.png", + stack_max = 1, + on_use = function(itemstack, user, pointed_thing) + local pname = user:get_player_name() + if not pname or pname == "" then + return + end + + --sanity checks in case of clicking the wrong entity/node/nothing + if pointed_thing.type ~= "object" then return end --not an entity + local object = pointed_thing.ref:get_luaentity() + if not object.id then return end --entity doesn't have an id field + + local wagon = advtrains.wagons[object.id] --check if wagon exists in advtrains + if not wagon then --not a wagon + return + end --end sanity checks + + --whitelist protection check + if not advtrains.check_driving_couple_protection(pname,wagon.owner,wagon.whitelist) then + minetest.chat_send_player(pname, attrans("Insufficient privileges to use this!")) + return + end + object:show_wagon_properties(pname) + return itemstack + end, +}) + +if minetest.get_modpath("default") then --register recipe + minetest.register_craft({ + output = "advtrains:wagon_prop_tool", + recipe = { + {"advtrains:dtrack_placer","dye:black","default:paper"}, + {"screwdriver:screwdriver","default:paper","default:paper"}, + {"","","group:wood"}, + } + }) +end \ No newline at end of file diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index 677014a..73200a3 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -868,6 +868,7 @@ function wagon:show_wagon_properties(pname) ]] local data = advtrains.wagons[self.id] local form="size[5,5]" + form=form.."label[0.2,0;"..attrans("This Wagon ID")..": "..self.id.."]" form = form .. "field[0.5,1;4.5,1;whitelist;Allow these players to access your wagon:;"..minetest.formspec_escape(data.whitelist or "").."]" form = form .. "field[0.5,2;4.5,1;roadnumber;Wagon road number:;"..minetest.formspec_escape(data.roadnumber or "").."]" local fc = "" -- cgit v1.2.3 From bed66e0f901ae9f8e21675035f174292120fea4f Mon Sep 17 00:00:00 2001 From: ywang Date: Sat, 27 Mar 2021 14:13:53 +0100 Subject: Rework translation system to use PO files The French translations are provided by Tanavit. Unfortunately I was not able to keep this addition as a separate commit as the translation file was originally added as a .tr file that I then converted to .po file in the meantime. Also note that this commit is created from squashing 20+ commits from the l10n branch that preceded the transition to PO files. In addition to changes to the locale files (which were all included in the single commit for transitioning to PO files), these commits also included code that has now become obsolete for l10n work. In particular, it included a GUI program written in Tcl to edit .tr files; this program can now be found in the following repo: https://codeberg.org/y5nw/mt_tr_editor Co-authored-by: Tanavit --- .gitignore | 1 + advtrains/copytool.lua | 16 +- advtrains/couple.lua | 4 +- advtrains/init.lua | 5 +- advtrains/locale/README.md | 69 ++++ advtrains/locale/advtrains.de.tr | 169 +++++++--- advtrains/locale/advtrains.fr.tr | 146 +++++++++ advtrains/locale/advtrains.zh_CN.tr | 135 +++++--- advtrains/locale/advtrains.zh_TW.tr | 146 +++++++++ advtrains/locale/gui | 638 ++++++++++++++++++++++++++++++++++++ advtrains/locale/template.txt | 146 +++++++++ advtrains/locale/topo.sh | 4 + advtrains/po/de.po | 580 ++++++++++++++++++++++++++++++++ advtrains/po/fr.po | 579 ++++++++++++++++++++++++++++++++ advtrains/po/template.pot | 505 ++++++++++++++++++++++++++++ advtrains/po/update-translations.sh | 24 ++ advtrains/po/zh_CN.po | 560 +++++++++++++++++++++++++++++++ advtrains/po/zh_TW.po | 560 +++++++++++++++++++++++++++++++ advtrains/protection.lua | 6 +- advtrains/signals.lua | 13 +- 20 files changed, 4194 insertions(+), 112 deletions(-) create mode 100644 advtrains/locale/README.md create mode 100644 advtrains/locale/advtrains.fr.tr create mode 100644 advtrains/locale/advtrains.zh_TW.tr create mode 100755 advtrains/locale/gui create mode 100644 advtrains/locale/template.txt create mode 100755 advtrains/locale/topo.sh create mode 100644 advtrains/po/de.po create mode 100644 advtrains/po/fr.po create mode 100644 advtrains/po/template.pot create mode 100755 advtrains/po/update-translations.sh create mode 100644 advtrains/po/zh_CN.po create mode 100644 advtrains/po/zh_TW.po (limited to 'advtrains/init.lua') diff --git a/.gitignore b/.gitignore index b3180de..2920966 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ ## Eclipse project files & directories .project .settings +*~ diff --git a/advtrains/copytool.lua b/advtrains/copytool.lua index 0c1cdfe..7ad4330 100644 --- a/advtrains/copytool.lua +++ b/advtrains/copytool.lua @@ -26,7 +26,7 @@ minetest.register_tool("advtrains:copytool", { return itemstack end if not minetest.check_player_privs(placer, {train_operator = true }) then - minetest.chat_send_player(pname, "You don't have the train_operator privilege.") + minetest.chat_send_player(pname, S("You do not have the @1 privilege.", "train_operator")) return itemstack end if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pointed_thing.under, placer:get_player_name()) then @@ -38,7 +38,7 @@ minetest.register_tool("advtrains:copytool", { local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid, {default=true}) if not prevpos then - minetest.chat_send_player(pname, "The track you are trying to place the wagon on is not long enough!") + minetest.chat_send_player(pname, attrans("The track you are trying to place the wagon on is not long enough!")) return end @@ -49,12 +49,12 @@ minetest.register_tool("advtrains:copytool", { end local clipboard = meta:get_string("clipboard") if (clipboard == "") then - minetest.chat_send_player(pname, "The clipboard is empty."); + minetest.chat_send_player(pname, attrans("The clipboard is empty.")); return end clipboard = minetest.deserialize(clipboard) if (clipboard.wagons == nil) then - minetest.chat_send_player(pname, "The clipboard is empty."); + minetest.chat_send_player(pname, attrans("The clipboard is empty.")); return end @@ -71,7 +71,7 @@ minetest.register_tool("advtrains:copytool", { local train = advtrains.trains[id] train.off_track = train.end_index= 0} { + if {$line eq ""} { + lappend translationTemplate $line + } elseif {[string match {#*} $line]} { + lappend translationTemplate $line + } elseif {[regexp {^(.+[^@])=.+$} $line x str]} { + lappend translationTemplate $str + } + } + close $handle +} + +proc readTranslationFiles {} { + global translationData translationLangs + array set translationData [list] + set translationLangs [list] + foreach fn [translationFilePaths] { + if {[regexp {\.([^.]+)\.tr$} $fn x lang]} { + set handle [open $fn "r"] + fconfigure $handle -translation lf + while {[gets $handle line] >= 0} { + if {[regexp {^([^#].+[^@])=(.+)$} $line x ori tr]} { + set translationData($lang,$ori) $tr + } + } + lappend translationLangs $lang + close $handle + } + } + set translationLangs [lsort $translationLangs] +} + +proc readTranslations {} { + readTranslationTemplate + readTranslationFiles +} + +proc writeTranslationTemplate {} { + global translationTemplate translationTemplatePath + set handle [open $translationTemplatePath "w"] + fconfigure $handle -translation lf + foreach line $translationTemplate { + if {$line eq ""} { + puts $handle "" + } elseif {[string match {#*} $line]} { + puts $handle $line + } else { + puts $handle "$line=$line" + } + } + close $handle +} + +proc writeTranslationFiles {} { + global translationDir translationDomain translationData translationLangs translationTemplate + foreach lang $translationLangs { + set handle [open [file join $translationDir "$translationDomain.$lang.tr"] "w"] + fconfigure $handle -translation lf + foreach i $translationTemplate { + if {$i eq ""} { + puts $handle "" + } elseif {[string match {#*} $i]} { + puts $handle $i + } else { + puts $handle [format "%s=%s" $i [getTranslationString $lang $i]] + } + } + close $handle + } +} + +proc writeTranslations {} { + writeTranslationTemplate + writeTranslationFiles +} + +proc hasTranslationString {lang str} { + return [expr {[getTranslationString $lang $str] ne $str}] +} + +proc maybeGetTranslationString {lang str} { + set tr [getTranslationString $lang $str] + if {$tr eq $str} { + return {} + } else { + return $tr + } +} + +proc getTranslationString {lang str} { + global translationData + if {[info exists translationData($lang,$str)]} { + return $translationData($lang,$str) + } else { + return $str + } +} + +proc setTranslationString {lang ori tr} { + global translationData + set translationData($lang,$ori) $tr +} + +proc rewordTranslationString {old new} { + global translationData translationLangs + foreach lang $translationLangs { + if {[hasTranslationString $lang $old]} { + setTranslationString $lang $new [getTranslationString $lang $old] + } else { + setTranslationString $lang $new $new + } + } +} + +# GUI helpers +proc gAddTab {basename title elems dummies} { + global gMainNotebook + gAddFrame $basename $elems $dummies + $gMainNotebook add "$gMainNotebook.$basename" -text $title +} + +proc gAddFrame {basename elems dummies} { + global gMainNotebook + set varbase [string cat "g" [firstupper $basename]] + set varname "${varbase}Frame" + set pathname "$gMainNotebook.$basename" + global $varname + set $varname $pathname + ttk::frame $pathname -padding 5 + foreach i $elems { + set varname [string cat $varbase [firstupper $i]] + global $varname + set $varname "$pathname.$i" + } + foreach i $dummies { + set varname [string cat $varbase [firstupper $i]] + global $varname + set $varname {} + } +} + +proc gReloadTranslations {} { + readTranslations + gTrLoadTranslations + gTmLoadTranslations +} + +proc gAddMenu {varname parent menuname entries} { + global $varname + set path "${parent}.${menuname}" + set $varname $path + $parent configure -menu [menu $path -tearoff false] + foreach i $entries { + $path add {*}$i + } + return $parent +} +set gMenuItemNotImplemented [list command -state disabled -label "(Not implemented)"] + +proc gNotImplemented {args} { + tk_messageBox -message "Not implemented" -icon error -type ok +} + +# Main window + +set gMainFrame ".f" +set gMainFrameWidgetCount 0 +foreach i [list readBtn writeBtn notebookTopSeparator notebook] { + set [string cat "gMain" [firstupper $i]] "$gMainFrame.$i" +} + +wm title . "Advtrains Translation File Editor" +grid rowconfigure . 0 -weight 1 +grid columnconfigure . 0 -weight 1 + +ttk::frame $gMainFrame +grid $gMainFrame -column 0 -row 0 -sticky nsew +grid rowconfigure $gMainFrame 2 -weight 1 + +foreach i [list \ + [ttk::button $gMainReadBtn -text "Reload translation files" -command gReloadTranslations] \ + [ttk::button $gMainWriteBtn -text "Write changes" -command writeTranslations] \ +] { + grid $i -column $gMainFrameWidgetCount -row 0 -sticky ns + incr gMainFrameWidgetCount +} + +grid columnconfigure $gMainFrame $gMainFrameWidgetCount -weight 1 + +ttk::separator $gMainNotebookTopSeparator -orient horizontal +grid $gMainNotebookTopSeparator -column 0 -row 1 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky ew + +ttk::notebook $gMainNotebook +grid $gMainNotebook -column 0 -row 2 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky nsew + +# Translation Manager +# FIXME?: it seems like Tcl requires -textvariable globals to be set first before they are accessible + +gAddTab tr "Translations" \ + [list langSelect refLangSelect readBtn writeBtn treeviewFrame origTextLabel origTextField translatedTextLabel translatedTextField refTextLabel refTextField] \ + [list langValue refLangValue origTextValue translatedTextValue refTextValue] +set gTrTreeview "$gTrTreeviewFrame.main" +set gTrTreeviewScrollbar "$gTrTreeviewFrame.scrollbar" + +grid rowconfigure $gTrFrame 0 -weight 1 +grid columnconfigure $gTrFrame 2 -weight 1 + +ttk::frame $gTrTreeviewFrame -borderwidth 1 -relief sunken +grid $gTrTreeviewFrame -column 0 -row 0 -columnspan 3 -sticky nsew +grid rowconfigure $gTrTreeviewFrame 0 -weight 1 +grid columnconfigure $gTrTreeviewFrame 0 -weight 1 +ttk::treeview $gTrTreeview -selectmode browse -columns {translation} -yscrollcommand {$gTrTreeviewScrollbar set} +grid $gTrTreeview -column 0 -row 0 -sticky nsew +bind $gTrTreeview <> gTrTreeviewSelectionCallback +ttk::scrollbar $gTrTreeviewScrollbar -orient vertical -command {$gTrTreeview yview} +grid $gTrTreeviewScrollbar -column 1 -row 0 -sticky ns +$gTrTreeview heading #0 -text "Original text" + +lmap i [list \ + [list \ + [ttk::label $gTrOrigTextLabel -text "Original" -anchor w] \ + {} \ + [ttk::entry $gTrOrigTextField -state readonly -textvariable gTrOrigTextValue] \ + ] \ + [list \ + [ttk::label $gTrTranslatedTextLabel -text "Translation" -anchor w] \ + [ttk::combobox $gTrLangSelect -exportselection false -state readonly -textvariable gTrLangValue] \ + [ttk::entry $gTrTranslatedTextField -textvariable gTrTranslatedTextValue] \ + ] \ + [list \ + [ttk::label $gTrRefTextLabel -text "Reference" -anchor w] \ + [ttk::combobox $gTrRefLangSelect -exportselection false -state readonly -textvariable gTrRefLangValue] \ + [ttk::entry $gTrRefTextField -state readonly -textvariable gTrRefTextValue] \ + ] \ +] row [list 1 2 3] { + lmap item $i col [list 0 1 2] { + if {$item eq ""} { + continue + } + grid $item -column $col -row $row -sticky nswe + } + grid rowconfigure $gTrFrame $row -uniform bottom + incr gTrRowCount +} + +bind $gTrLangSelect <> gTrLoadTranslationsToTreeview +trace add variable gTrTranslatedTextValue write gTrApplyTranslationString +bind $gTrRefLangSelect <> gTrTreeviewSelectionCallback + +proc gTrLoadTranslationsToTreeview {} { + global translationTemplate gTrTreeview gTrLangValue + $gTrTreeview heading translation -text "Translation: $gTrLangValue" + set prevFocus [$gTrTreeview item [$gTrTreeview focus] -text] + array set openedSections [list] + foreach i [$gTrTreeview children {}] { + if {[$gTrTreeview item $i -open]} { + set openedSections([$gTrTreeview item $i -text]) 1 + } + } + $gTrTreeview delete [$gTrTreeview children {}] + set parent {} + foreach i [lrange $translationTemplate 1 end] { + if {[regexp {^\#+\s*(.+)} $i x comment]} { + set parent [$gTrTreeview insert {} end -text $comment -tags {notranslate}] + if {[info exists openedSections($comment)]} { + $gTrTreeview item $parent -open true + } + if {$comment eq $prevFocus} { + $gTrTreeview focus $parent + $gTrTreeview selection set $parent + } + } elseif {$i ne ""} { + set last [$gTrTreeview insert $parent end -text $i -values [list [maybeGetTranslationString $gTrLangValue $i]]] + if {$i eq $prevFocus} { + $gTrTreeview focus $last + $gTrTreeview selection set $last + } + } + } + gTrTreeviewSelectionCallback +} + +proc gTrTreeviewSelectionCallback {} { + global gTrOrigTextValue gTrTreeview gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue gTrTranslatedTextField gTrTranslatedTextValue gTrRefTextField gTrRefTextValue + set focused [$gTrTreeview focus] + set gTrOrigTextValue [$gTrTreeview item $focused -text] + if {$focused eq ""} { + $gTrTranslatedTextField state disabled + $gTrRefTextField state disabled + set gTrTranslatedTextValue "Select an entry to translate" + set gTrRefTextValue "" + } elseif {[$gTrTreeview tag has notranslate $focused]} { + $gTrTranslatedTextField state disabled + $gTrRefTextField state disabled + set gTrTranslatedTextValue "Category names cannot be translated" + set gTrRefTextValue "" + } else { + $gTrTranslatedTextField state !disabled + set gTrTranslatedTextValue [maybeGetTranslationString $gTrLangValue $gTrOrigTextValue] + set gTrRefTextValue [maybeGetTranslationString $gTrRefLangValue $gTrOrigTextValue] + if {$gTrRefLangValue eq ""} { + $gTrRefTextField state disabled + set gTrRefTextValue "" + } elseif {$gTrRefTextValue eq ""} { + $gTrRefTextField state disabled + set gTrRefTextValue "The selected string is not yet translated to the reference language" + } else { + $gTrRefTextField state !disabled + } + } + $gTrLangSelect selection clear + $gTrRefLangSelect selection clear +} + +proc gTrLoadTranslations {} { + global translationLangs gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue + set prevLang $gTrLangValue + set prevRefLang $gTrRefLangValue + $gTrLangSelect configure -values $translationLangs + $gTrRefLangSelect configure -values [linsert $translationLangs 0 ""] + if {[llength $translationLangs] < 1} { + tk_messageBox -icon error type ok -title "Error" -message "No translation files present." + exit 1 + } + if {$prevLang ni $translationLangs} { + $gTrLangSelect current 0 + } + if {$prevRefLang ni $translationLangs} { + $gTrRefLangSelect current 0 + } + gTrLoadTranslationsToTreeview +} + +proc gTrApplyTranslationString args { + global gTrTreeview gTrLangValue gTrOrigTextValue gTrTranslatedTextValue + set focused [$gTrTreeview focus] + if {![$gTrTreeview tag has notranslate $focused]} { + setTranslationString $gTrLangValue $gTrOrigTextValue $gTrTranslatedTextValue + $gTrTreeview item $focused -values [list $gTrTranslatedTextValue] + } +} + +# Translation Template Editor + +gAddTab tm "Template" \ + [list addStringMenuBtn addHeadingMenuBtn removeMenuBtn moveMenuBtn textField setMenuBtn treeviewFrame] \ + [list textValue] +set gTmTreeview "$gTmTreeviewFrame.main" +set gTmTreeviewScrollbar "$gTmTreeviewFrame.scrollbar" + +set gTmRowCount 0 +foreach i [list \ + [gAddMenu gTmAddStringMenu [ttk::menubutton $gTmAddStringMenuBtn -text "Add string"] "menu" [list \ + [list command -label "Insert before current entry" -command {gTmInsertStringAt true 0}] \ + [list command -label "Insert after current entry" -command {gTmInsertStringAt true 1}] \ + [list command -label "Insert as the first entry" -command {gTmInsertStringAt false 0}] \ + [list command -label "Insert as the last entry" -command {gTmInsertStringAt false end}] \ + ]] \ + [gAddMenu gTmAddHeadingMenu [ttk::menubutton $gTmAddHeadingMenuBtn -text "Add heading"] "menu" [list \ + [list command -label "Insert before current section" -command {gTmInsertHeadingAt true 0}] \ + [list command -label "Insert after current section" -command {gTmInsertHeadingAt true 1}] \ + ]] \ + [gAddMenu gTmRemoveMenu [ttk::menubutton $gTmRemoveMenuBtn -text "Remove"] "menu" [list \ + [list command -label "Remove entry" -command gTmDeleteEntry] \ + [list command -label "Remove section" -command gTmDeleteEntry] \ + [list command -label "Merge with previous section" -command gTmMergeWithPrevious] \ + ]] \ + [gAddMenu gTmMoveMenu [ttk::menubutton $gTmMoveMenuBtn -text "Move"] "menu" [list \ + [list command -label "Up" -command {gTmMoveInSection true -1}] \ + [list command -label "Down" -command {gTmMoveInSection true 1}] \ + [list command -label "To first" -command {gTmMoveInSection false 0}] \ + [list command -label "To last" -command {gTmMoveInSection false end}] \ + ]] \ +] { + grid $i -column 1 -row $gTmRowCount -sticky we + incr gTmRowCount +} + +ttk::frame $gTmTreeviewFrame -borderwidth 1 -relief sunken +grid $gTmTreeviewFrame -column 0 -row 0 -rowspan [expr {1+$gTmRowCount}] -sticky nsew +grid rowconfigure $gTmTreeviewFrame 0 -weight 1 +grid columnconfigure $gTmTreeviewFrame 0 -weight 1 +grid rowconfigure $gTmFrame $gTmRowCount -weight 1 +grid columnconfigure $gTmFrame 0 -weight 1 +ttk::treeview $gTmTreeview -selectmode browse -show tree -yscrollcommand {$gTmTreeviewScrollbar set} +bind $gTmTreeview <> gTmTreeviewSelectionCallback +grid $gTmTreeview -column 0 -row 0 -sticky nsew +ttk::scrollbar $gTmTreeviewScrollbar -orient vertical -command {$gTmTreeview yview} +grid $gTmTreeviewScrollbar -column 1 -row 0 -sticky ns +incr gTmRowCount + +ttk::entry $gTmTextField -textvariable gTmTextValue +grid $gTmTextField -column 0 -row $gTmRowCount -sticky nsew + +gAddMenu gTmSetMenu [ttk::menubutton $gTmSetMenuBtn -text "Set"] "menu" [list \ + [list command -label "Set heading" -command gTmSetEntry] \ + [list command -label "Set and copy translations" -command gTmSetEntryAndCopy] \ + [list command -label "Set without copying translations" -command gTmSetEntry] \ +] +grid $gTmSetMenuBtn -column 1 -row $gTmRowCount -sticky nsew + +proc gTmLoadTranslationsToTreeview {} { + global translationTemplate gTmTreeview + set prevFocus [$gTmTreeview item [$gTmTreeview focus] -text] + array set openedSections [list] + foreach i [$gTmTreeview children {}] { + if {[$gTmTreeview item $i -open]} { + set openedSections([$gTmTreeview item $i -text]) 1 + } + } + $gTmTreeview delete [$gTmTreeview children {}] + set parent {} + foreach i [lrange $translationTemplate 1 end] { + if {[regexp {^\#+\s*(.+)} $i x comment]} { + set parent [$gTmTreeview insert {} end -text $comment -tags {heading}] + if {[info exists openedSections($comment)]} { + $gTmTreeview item $parent -open true + } + if {$comment eq $prevFocus} { + $gTmTreeview focus $parent + $gTmTreeview selection set $parent + } + } elseif {$i ne ""} { + set last [$gTmTreeview insert $parent end -text $i] + if {$i eq $prevFocus} { + $gTmTreeview focus $last + $gTmTreeview selection set $last + } + } + } + gTmTreeviewSelectionCallback +} + +proc gTmTreeviewSelectionCallback {} { + global gTmTreeview gTmTextField gTmTextValue gTmAddStringMenu gTmAddHeadingMenu gTmRemoveMenu gTmMoveMenu gTmSetMenu + set focused [$gTmTreeview focus] + if {$focused eq {}} { + $gTmTextField state disabled + set gTmTextValue "Select an entry to edit" + foreach m [list $gTmAddStringMenu $gTmAddHeadingMenu $gTmRemoveMenu $gTmMoveMenu $gTmSetMenu] { + for {set i 0} {$i <= [$m index end]} {incr i} { $m entryconfigure $i -state disabled} + } + } else { + $gTmTextField state !disabled + set headingSetState disabled + set entrySetState normal + if {[$gTmTreeview tag has heading $focused]} { + set headingSetState normal + set entrySetState disabled + } + foreach ent [list \ + [list $gTmAddStringMenu \ + [list 0 -state $entrySetState] \ + [list 1 -state $entrySetState] \ + [list 2 -state normal] \ + [list 3 -state normal] \ + ] \ + [list $gTmAddHeadingMenu \ + [list 0 -state normal] \ + [list 1 -state normal] \ + ] \ + [list $gTmMoveMenu \ + [list 0 -state normal] \ + [list 1 -state normal] \ + [list 2 -state normal] \ + [list 3 -state normal] \ + ] \ + [list $gTmRemoveMenu \ + [list 0 -state $entrySetState] \ + [list 1 -state $headingSetState] \ + [list 2 -state $headingSetState] \ + ] \ + [list $gTmSetMenu \ + [list 0 -state $headingSetState] \ + [list 1 -state $entrySetState] \ + [list 2 -state $entrySetState] \ + ] \ + ] { + set m [lindex $ent 0] + lmap i [lrange $ent 1 end] { + $m entryconfigure {*}$i + } + } + set gTmTextValue [$gTmTreeview item $focused -text] + } +} + +proc gTmUpdateTemplateAux {parent} { + global translationTemplate gTmTreeview + foreach i [$gTmTreeview children $parent] { + set tval [$gTmTreeview item $i -text] + if {[$gTmTreeview tag has heading $i]} { + lappend translationTemplate {} + set tval "# $tval" + } + lappend translationTemplate $tval + gTmUpdateTemplateAux $i + } +} + +proc gTmUpdateTemplate {} { + global translationTemplate translationDomain + set translationTemplate [list "# textdomain: $translationDomain"] + gTmUpdateTemplateAux {} + gTrLoadTranslations + gTmLoadTranslationsToTreeview +} + +proc gTmSetEntry {} { + global gTmTreeview gTmTextValue + $gTmTreeview item [$gTmTreeview focus] -text $gTmTextValue + gTmUpdateTemplate +} + +proc gTmSetEntryAndCopy {} { + global gTmTreeview gTmTextValue + set focus [$gTmTreeview focus] + rewordTranslationString [$gTmTreeview item $focus -text] $gTmTextValue + gTmSetEntry +} + +proc gTmInsertStringAt {relative idx} { + global gTmTreeview + set focus [$gTmTreeview focus] + set parent [$gTmTreeview parent $focus] + set relidx [$gTmTreeview index $focus] + if {[$gTmTreeview tag has heading $focus]} { + set parent $focus + set relindex 0 + } + set newidx $idx + if {$relative} { + set newidx [expr {$idx+$relidx}] + } + set item [$gTmTreeview insert $parent $newidx -text {}] + $gTmTreeview focus $item + $gTmTreeview selection set $item +} + +proc gTmInsertHeadingAt {relative idx} { + global gTmTreeview + set focus [$gTmTreeview focus] + if {![$gTmTreeview tag has heading $focus]} { + set focus [$gTmTreeview parent $focus] + } + set parent [$gTmTreeview parent $focus] + set relidx [$gTmTreeview index $focus] + if {$focus eq {}} { + set parent {} + set relidx 0 + } + set newidx $idx + if {$relative} { + set newidx [expr {$idx+$relidx}] + } + set item [$gTmTreeview insert $parent $newidx -text {} -tags {heading}] + $gTmTreeview focus $item + $gTmTreeview selection set $item +} + +proc gTmMoveInSection {relative idx} { + global gTmTreeview + set focus [$gTmTreeview focus] + set parent [$gTmTreeview parent $focus] + set relidx [$gTmTreeview index $focus] + set newidx $idx + if {$relative} { + set newidx [expr {$idx+$relidx}] + } + $gTmTreeview move $focus $parent $newidx + gTmUpdateTemplate +} + +proc gTmDeleteEntry {} { + global gTmTreeview + $gTmTreeview delete [$gTmTreeview focus] + gTmUpdateTemplate +} + +proc gTmMergeWithPrevious {} { + global gTmTreeview + set parent [$gTmTreeview focus] + set prev [$gTmTreeview prev $parent] + set newindex end + if {$prev eq {}} { + set prev [$gTmTreeview parent $parent] + set newindex 0 + } + foreach i [$gTmTreeview children $parent] { + $gTmTreeview move $i $prev $newindex + } + $gTmTreeview delete $parent + gTmUpdateTemplate +} + +proc gTmLoadTranslations {} { + gTmLoadTranslationsToTreeview +} + +# Initialization + +gReloadTranslations diff --git a/advtrains/locale/template.txt b/advtrains/locale/template.txt new file mode 100644 index 0000000..8c8b859 --- /dev/null +++ b/advtrains/locale/template.txt @@ -0,0 +1,146 @@ +# textdomain: advtrains + +# Advtrains Core (unorganized) +This wagon is owned by @1, you can't destroy it.=This wagon is owned by @1, you can't destroy it. +Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon. +This position is protected!=This position is protected! +Can't place: not pointing at node=Can't place: not pointing at node +Can't place: space occupied!=Can't place: space occupied! +Can't place: protected position!=Can't place: protected position! +Can't place: Not enough slope items left (@1 required)=Can't place: Not enough slope items left (@1 required) +Can't place: There's no slope of length @1=Can't place: There's no slope of length @1 +Can't place: no supporting node at upper end.=Can't place: no supporting node at upper end. +Deprecated Track=Deprecated Track +Can't get on: wagon full or doors closed!=Can't get on: wagon full or doors closed! +Use Sneak+rightclick to bypass closed doors!=Use Sneak+rightclick to bypass closed doors! +Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off! +Access to @1=Access to @1 +You do not have the @1 privilege.=You do not have the @1 privilege. +The wagon's inventory is not empty!=The wagon's inventory is not empty! +Position is occupied by a train.=Position is occupied by a train. +There's a Track Circuit Break here.=There's a Track Circuit Break here. +There's a Signal Influence Point here.=There's a Signal Influence Point here. + +# Trackworker, rotation, adjustment +This node can't be rotated using the trackworker!=This node can't be rotated using the trackworker! +This node can't be changed using the trackworker!=This node can't be changed using the trackworker! +This track can not be changed!=This track can not be changed! +This track can not be rotated!=This track can not be rotated! +This track can not be removed!=This track can not be removed! + +# ATC +ATC controller, unconfigured.=ATC controller, unconfigured. +ATC controller=ATC controller +ATC controller, mode @1@nChannel: @2=ATC controller, mode @1@nChannel: @2 +ATC controller, mode @1@nCommand: @2=ATC controller, mode @1@nCommand: @2 +Command=Command +Command (on)=Command (on) +Digiline channel=Digiline channel +ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed +ATC Kick command warning: Train moving=ATC Kick command warning: Train moving +ATC Reverse command warning: didn't reverse train, train moving!=ATC Reverse command warning: didn't reverse train, train moving! +ATC command syntax error: I statement not closed: @1=ATC command syntax error: I statement not closed: @1 +ATC command parse error: Unknown command: @1=ATC command parse error: Unknown command: @1 + +# Coupling +Lock couples=Lock couples +You need to own at least one neighboring wagon to destroy this couple.=You need to own at least one neighboring wagon to destroy this couple. +Buffer and Chain Coupler=Buffer and Chain Coupler +Scharfenberg Coupler=Scharfenberg Coupler +Japanese Train Inter-Wagon Connection=Japanese Train Inter-Wagon Connection +Can not couple: The couplers of the trains do not match (@1 and @2).=Can not couple: The couplers of the trains do not match (@1 and @2). +You are not allowed to couple trains without the train_operator privilege.=You are not allowed to couple trains without the train_operator privilege. + +# Clipboard +The track you are trying to place the wagon on is not long enough!=The track you are trying to place the wagon on is not long enough! +The clipboard couldn't access the metadata. Paste failed.=The clipboard couldn't access the metadata. Paste failed. +The clipboard couldn't access the metadata. Copy failed.=The clipboard couldn't access the metadata. Copy failed. +The clipboard is empty.=The clipboard is empty. +Back of train would end up off track, cancelling.=Back of train would end up off track, cancelling. +No such lua entity!=No such lua entity! +No such wagon: @1=No such wagon: @1 +No such train: @1=No such train: @1 +Train copied!=Train copied! + +# Protection +You are not allowed to build tracks without the track_builder privilege.=You are not allowed to build tracks without the track_builder privilege. +You are not allowed to build near tracks without the track_builder privilege.=You are not allowed to build near tracks without the track_builder privilege. +You are not allowed to build tracks at this protected position.=You are not allowed to build tracks at this protected position. +You are not allowed to build near tracks at this protected position.=You are not allowed to build near tracks at this protected position. +You are not allowed to operate turnouts and signals without the railway_operator privilege.=You are not allowed to operate turnouts and signals without the railway_operator privilege. + +# Train HUD/Formspecs +Speed:=Speed: +Target:=Target: +Show Inventory=Show Inventory +Select seat:=Select seat: +Wagon properties=Wagon properties +Save wagon properties=Save wagon properties +Text displayed outside on train=Text displayed outside on train +Text displayed inside train=Text displayed inside train +Line=Line +Routingcode=Routingcode +Get off=Get off +Get off (forced)=Get off (forced) +(Doors closed)=(Doors closed) + +# General +Save=Save + +# Line automation +Station Code=Station Code +Station Name=Station Name +Door Delay=Door Delay +Door Side=Door Side +Dep. Speed=Dep. Speed +Stop Time=Stop Time + +# Items +Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc. +Passive Component Naming Tool@n@nRight-click to name a passive component.=Passive Component Naming Tool@n@nRight-click to name a passive component. +Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train +Track=Track +Perpendicular Diamond Crossing Track=Perpendicular Diamond Crossing Track +Diagonal Diamond Crossing Track=Diagonal Diamond Crossing Track +90+Angle Diamond Crossing Track=90+Angle Diamond Crossing Track +Y-turnout=Y-turnout +3-way turnout=3-way turnout +Unloading Track=Unloading Track +Loading Track=Loading Track +Bumper=Bumper +Detector Rail=Detector Rail +@1 Slope=@1 Slope +@1 Platform (low)=@1 Platform (low) +@1 Platform (high)=@1 Platform (high) +@1 Platform (low, 45 degree)=@1 Platform (low, 45 degree) +@1 Platform (45 degree)=@1 Platform (45 degree) +Lampless Signal=Lampless Signal +Signal=Signal +Wallmounted Signal (l)=Wallmounted Signal (l) +Wallmounted Signal (r)=Wallmounted Signal (r) +Wallmounted Signal (t)=Wallmounted Signal (t) +Andrew's Cross=Andrew's Cross +Boiler=Boiler +driver's cab=driver's cab +Wheel=Wheel +Chimney=Chimney + +# Seats +Default Seat=Default Seat +Default Seat (driver stand)=Default Seat (driver stand) +Driver stand=Driver stand +Driver Stand (left)=Driver Stand (left) +Driver Stand (right)=Driver Stand (right) + +# Wagon/engine types +Industrial Train Engine=Industrial Train Engine +Big Industrial Train Engine=Big Industrial Train Engine +Industrial tank wagon=Industrial tank wagon +Industrial wood wagon=Industrial wood wagon +Japanese Train Engine=Japanese Train Engine +Japanese Train Wagon=Japanese Train Wagon +Steam Engine=Steam Engine +Detailed Steam Engine=Detailed Steam Engine +Passenger Wagon=Passenger Wagon +Box Wagon=Box Wagon +Subway Passenger Wagon=Subway Passenger Wagon diff --git a/advtrains/locale/topo.sh b/advtrains/locale/topo.sh new file mode 100755 index 0000000..23f81b1 --- /dev/null +++ b/advtrains/locale/topo.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +head -n18 ../po/template.pot | sed 's/charset=CHARSET/charset=UTF-8/' +sed -En 's/@n/\\n/g;s/@\n/\\n/g;s/\"/\\"/g;s/^([^=]+)=\1$/\1=/;s/^([^=]+)=([^=]*)$/\nmsgid "\1"\nmsgstr "\2"/gp' diff --git a/advtrains/po/de.po b/advtrains/po/de.po new file mode 100644 index 0000000..ebd6339 --- /dev/null +++ b/advtrains/po/de.po @@ -0,0 +1,580 @@ +msgid "" +msgstr "" +"Project-Id-Version: advtrains\n" +"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" +"POT-Creation-Date: 2023-10-04 15:40+0200\n" +"PO-Revision-Date: 2022-11-02 15:08+0100\n" +"Last-Translator: Y. Wang \n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: advtrains/atc.lua:109 +msgid "ATC controller, unconfigured." +msgstr "Nicht konfiguierte Zugbeeinflussungsgleis" + +#: advtrains/atc.lua:150 +msgid "" +"ATC controller, mode @1\n" +"Command: @2" +msgstr "" +"Zugbeeinflussungsgleis in Betriebsart „@1“\n" +"Befehl: @2" + +#: advtrains/atc.lua:180 +msgid "Command" +msgstr "Befehl" + +#: advtrains/atc.lua:184 +msgid "Command (on)" +msgstr "Befehl (wenn aktiviert)" + +#: advtrains/atc.lua:187 +msgid "Digiline channel" +msgstr "Digiline-Kanal" + +#: advtrains/atc.lua:189 advtrains_line_automation/stoprail.lua:65 +msgid "Save" +msgstr "Speichern" + +#: advtrains/atc.lua:236 +msgid "ATC Reverse command warning: didn't reverse train, train moving!" +msgstr "" +"Zugbeeinflussung: der Befehl „R“ wurde nicht ausgeführt, Zug in Bewegung!" + +#: advtrains/atc.lua:248 +msgid "ATC Kick command warning: Doors closed" +msgstr "" + +#: advtrains/atc.lua:252 +msgid "ATC Kick command warning: Train moving" +msgstr "" + +#: advtrains/atc.lua:322 +msgid "ATC command syntax error: I statement not closed: @1" +msgstr "Zugbeeinflussung: Unvollständiger I-Befehl: @1" + +#: advtrains/atc.lua:385 +msgid "ATC command parse error: Unknown command: @1" +msgstr "Zugbeeinflussung: Unbekannter Befehl: @1" + +#: advtrains/craft_items.lua:3 +msgid "Boiler" +msgstr "" + +#: advtrains/craft_items.lua:9 +msgid "driver's cab" +msgstr "" + +#: advtrains/craft_items.lua:15 +msgid "Wheel" +msgstr "" + +#: advtrains/craft_items.lua:21 +msgid "Chimney" +msgstr "" + +#: advtrains/misc_nodes.lua:16 +msgid "@1 Platform (low)" +msgstr "Niedriger @1-Bahnsteig" + +#: advtrains/misc_nodes.lua:33 +msgid "@1 Platform (high)" +msgstr "Hoher @1-Bahnsteig" + +#: advtrains/misc_nodes.lua:59 +msgid "@1 Platform (45 degree)" +msgstr "Hoher @1-Bahnsteig (45°)" + +#: advtrains/misc_nodes.lua:81 +msgid "@1 Platform (low, 45 degree)" +msgstr "Niedriger @1-Bahnsteig (45°)" + +#: advtrains/trackplacer.lua:313 +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate rail/bumper/signal/etc." +msgstr "" +"Gleiswerkzeug\n" +"\n" +"Linksklick: Gleistyp ändern, Rechtsklick: Objekt drehen." + +#: advtrains/trackplacer.lua:340 advtrains/trackplacer.lua:377 +msgid "This node can't be rotated using the trackworker!" +msgstr "Dieser Block kann nicht mit dem Gleiswerkzeug gedreht werden." + +#: advtrains/trackplacer.lua:350 +msgid "This track can not be rotated!" +msgstr "Dieses Gleis kann nicht gedreht werden!" + +#: advtrains/trackplacer.lua:404 +msgid "This node can't be changed using the trackworker!" +msgstr "Dieser Block kann nicht mit dem Gleiswerkzeug bearbeitet werden." + +#: advtrains/trackplacer.lua:414 +msgid "This track can not be changed!" +msgstr "Dieses Gleis kann nicht geändert werden!" + +#: advtrains/wagons.lua:179 +msgid "This wagon is owned by @1, you can't destroy it." +msgstr "Dieser Waggon gehört @1, Sie dürfen ihn nicht abbauen." + +#: advtrains/wagons.lua:203 +msgid "The wagon's inventory is not empty!" +msgstr "Das Inventar dieses Waggons ist nicht leer!" + +#: advtrains/wagons.lua:210 +msgid "Wagon needs to be decoupled from other wagons in order to destroy it." +msgstr "" + +#: advtrains/wagons.lua:216 +msgid "" +"Warning: If you destroy this wagon, you only get some steel back! If you are " +"sure, hold Sneak and left-click the wagon." +msgstr "" +"Warnung: Durch den Abbau des Waggons erhalten Sie nur etwas Stahl zurück. " +"Nutzen Sie Schleichen+Linksklick, um dem Waggon abzubauen." + +#: advtrains/wagons.lua:649 advtrains/wagons.lua:850 +msgid "Show Inventory" +msgstr "Inventar Zeigen" + +#: advtrains/wagons.lua:652 +msgid "Onboard Computer" +msgstr "" + +#: advtrains/wagons.lua:655 advtrains/wagons.lua:1328 +msgid "Wagon properties" +msgstr "Waggon-Einstellungen" + +#: advtrains/wagons.lua:658 +msgid "Get off" +msgstr "Aussteigen" + +#: advtrains/wagons.lua:661 +msgid "Get off (forced)" +msgstr "Ausstieg zwingen" + +#: advtrains/wagons.lua:663 +msgid "(Doors closed)" +msgstr "(Türen geschlossen)" + +#: advtrains/wagons.lua:712 +msgid "Can't get on: " +msgstr "" + +#: advtrains/wagons.lua:838 +msgid "Select seat:" +msgstr "Wählen Sie einen Sitzplatz aus:" + +#: advtrains/wagons.lua:880 +msgid "Save wagon properties" +msgstr "Waggon-Einstellungen speichern" + +#: advtrains/wagons.lua:965 +msgid "Text displayed outside on train" +msgstr "Äußere Anzeige" + +#: advtrains/wagons.lua:966 +msgid "Text displayed inside train" +msgstr "Innere Anzeige" + +#: advtrains/wagons.lua:967 +msgid "Line" +msgstr "Linie" + +#: advtrains/wagons.lua:968 +msgid "Routingcode" +msgstr "" + +#: advtrains/wagons.lua:1241 +msgid "" +"Doors are closed! Use Sneak+rightclick to ignore the closed doors and get " +"off!" +msgstr "" +"Die Türen sind geschlossen. Nutzen Sie Schleichen+Rechtsklick, um trotz " +"geschlossener Türen auszusteigen." + +#: advtrains/trainhud.lua:305 +msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." +msgstr "" + +#: advtrains/tracks.lua:449 +msgid "This track can not be removed!" +msgstr "Dieses Gleis kann nicht entfernt werden!" + +#: advtrains/tracks.lua:616 +msgid "Position is occupied by a train." +msgstr "Ein Zug steht an dieser Position." + +#: advtrains/tracks.lua:622 +msgid "There's a Track Circuit Break here." +msgstr "Hier ist eine Gleisabschnittsgrenze (TCB)." + +#: advtrains/tracks.lua:626 +msgid "There's a Signal Influence Point here." +msgstr "Hier ist ein Signal-Beeinflussungspunkt." + +#: advtrains/tracks.lua:637 +msgid "@1 Slope" +msgstr "@1 Steigung" + +#: advtrains/tracks.lua:648 advtrains/tracks.lua:653 +msgid "Can't place: not pointing at node" +msgstr "Es kann nicht platziert werden: Sie zeigen nicht auf einem Block." + +#: advtrains/tracks.lua:658 +msgid "Can't place: space occupied!" +msgstr "Es kann nicht platziert werden: diese Position ist besetzt." + +#: advtrains/tracks.lua:711 +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "" +"Es kann nicht platziert werden: Sie haben nicht genug Steigungsblöcke, es " +"werden insgesamt @1 benötigt." + +#: advtrains/tracks.lua:714 +msgid "Can't place: There's no slope of length @1" +msgstr "" +"Es kann nicht platziert werden: die Steigung der Länge @1 ist nicht " +"definiert." + +#: advtrains/tracks.lua:721 +msgid "Can't place: no supporting node at upper end." +msgstr "" +"Es kann nicht platziert werden: es gibt keinen unterstützenden Block am Ende " +"der Steigung." + +#: advtrains/signals.lua:63 +msgid "Lampless Signal" +msgstr "Mechanisches Signal" + +#: advtrains/signals.lua:127 +msgid "Signal" +msgstr "Lichtsignal" + +#: advtrains/signals.lua:191 +msgid "Wallmounted Signal (l)" +msgstr "An der linken Seite montiertes Signal" + +#: advtrains/signals.lua:192 +msgid "Wallmounted Signal (r)" +msgstr "An der rechten Seite montiertes Signal" + +#: advtrains/signals.lua:193 +msgid "Wallmounted Signal (t)" +msgstr "An der Decke montiertes Signal" + +#: advtrains/signals.lua:281 advtrains/signals.lua:322 +msgid "Andrew's Cross" +msgstr "" + +#: advtrains/couple.lua:28 +msgid "Buffer and Chain Coupler" +msgstr "Schraubenkupplung" + +#: advtrains/couple.lua:29 +msgid "Scharfenberg Coupler" +msgstr "Scharfenbergkupplung" + +#: advtrains/couple.lua:185 +msgid "" +"You are not allowed to couple trains without the train_operator privilege." +msgstr "Sie dürfen ohne das „train_builder“-Privileg keine Züge ankuppeln." + +#: advtrains/couple.lua:329 advtrains/couple.lua:333 +msgid "" +msgstr "" + +#: advtrains/couple.lua:334 +msgid "Can not couple: The couplers of the trains do not match (@1 and @2)." +msgstr "Die Kupplungen der Züge passen nicht zueinander (@1 und @2)." + +#: advtrains/copytool.lua:8 +msgid "" +"Train copy/paste tool\n" +"\n" +"Left-click: copy train\n" +"Right-click: paste train" +msgstr "" +"Werkzeug zur Erstellung von Zugkopien\n" +"\n" +"Linksklick: Zug ins Clipboard kopieren\n" +"Right-click: Kopierten Zug einfügen" + +#: advtrains/copytool.lua:29 +msgid "You do not have the @1 privilege." +msgstr "Ihnen fehlt das „@1“-Privileg." + +#: advtrains/copytool.lua:41 +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "Das Gleis, auf dem der Waggon platziert werden woll, ist zu kurz." + +#: advtrains/copytool.lua:47 +msgid "The clipboard couldn't access the metadata. Paste failed." +msgstr "" +"Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte eine Kopie des " +"Zuges nicht eingefügt werden." + +#: advtrains/copytool.lua:52 advtrains/copytool.lua:57 +msgid "The clipboard is empty." +msgstr "Das Clipboard ist leer." + +#: advtrains/copytool.lua:74 +msgid "Back of train would end up off track, cancelling." +msgstr "Der hinterer Teil dez Zuges wäre nicht auf dem Gleis." + +#: advtrains/copytool.lua:92 +msgid "No such lua entity!" +msgstr "" +"Sie zeigen nicht auf einem Objekt, das mit diesem Werkzeug kopiert werden " +"kann." + +#: advtrains/copytool.lua:98 +msgid "No such wagon: @1" +msgstr "Es gibt keinen mit „@1“ identifizierbaren Waggon." + +#: advtrains/copytool.lua:104 +msgid "No such train: @1" +msgstr "Es gibt keinen mit „@1“ identifizierbaren Zug." + +#: advtrains/copytool.lua:176 +msgid "The clipboard couldn't access the metadata. Copy failed." +msgstr "" +"Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte der Zug nicht " +"kopiert werden." + +#: advtrains/copytool.lua:180 +msgid "Train copied!" +msgstr "Der Zug wurde Kopiert." + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build near tracks without the track_builder privilege." +msgstr "" +"Sie dürfen ohne das „track_builder“-Privileg nicht in der Nähe von Gleisen " +"bauen." + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build tracks without the track_builder privilege." +msgstr "Sie dürfen ohne das „track_builder“-Privileg kein Gleis bauen." + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build near tracks at this protected position." +msgstr "Sie dürfen an geschützten Stellen nicht in der Nähe von Gleisen bauen." + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build tracks at this protected position." +msgstr "Sie dürfen an geschützten Stellen kein Gleis bauen." + +#: advtrains/protection.lua:184 +msgid "" +"You are not allowed to operate turnouts and signals without the " +"railway_operator privilege." +msgstr "" +"Sie dürfen ohne das „railway_operator“-Privileg keine Bahnanlage operieren." + +#: advtrains_line_automation/stoprail.lua:54 +msgid "Station Code" +msgstr "Code der Haltestelle" + +#: advtrains_line_automation/stoprail.lua:55 +msgid "Station Name" +msgstr "Name der Haltestelle" + +#: advtrains_line_automation/stoprail.lua:56 +msgid "Door Delay" +msgstr "Zeit für die Türschließung" + +#: advtrains_line_automation/stoprail.lua:57 +msgid "Dep. Speed" +msgstr "Zielgeschwindigkeit bei Abfahrt" + +#: advtrains_line_automation/stoprail.lua:58 advtrains_train_track/init.lua:11 +#: advtrains_train_track/init.lua:156 +msgid "Track" +msgstr "Gleis" + +#: advtrains_line_automation/stoprail.lua:59 +msgid "Stop Time" +msgstr "Wartezeit" + +#: advtrains_line_automation/stoprail.lua:60 +msgid "Door Side" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:62 +msgid "Reverse train" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:63 +msgid "Kick out passengers" +msgstr "" + +#: advtrains_luaautomation/pcnaming.lua:26 +msgid "" +"Passive Component Naming Tool\n" +"\n" +"Right-click to name a passive component." +msgstr "" +"PC-Benennungswerkzeug\n" +"\n" +"Rechtsklick zur Benennung der passiven Komponente" + +#: advtrains_train_track/init.lua:31 +msgid "Y-turnout" +msgstr "Y-Weiche" + +#: advtrains_train_track/init.lua:49 +msgid "3-way turnout" +msgstr "Dreiwegweiche" + +#: advtrains_train_track/init.lua:69 +msgid "Perpendicular Diamond Crossing Track" +msgstr "Kreuzung mit zueinander orthogonalen Gleisen" + +#: advtrains_train_track/init.lua:91 +msgid "90+Angle Diamond Crossing Track" +msgstr "Kreuzung mit einem achsenparallelen Gleis" + +#: advtrains_train_track/init.lua:132 +msgid "Diagonal Diamond Crossing Track" +msgstr "Diagonale Gleiskreuzung" + +#: advtrains_train_track/init.lua:179 +msgid "Bumper" +msgstr "Prellbock" + +#: advtrains_train_track/init.lua:201 +msgid "ATC controller" +msgstr "Zugbeeinflussungsgleis" + +#: advtrains_train_track/init.lua:317 +msgid "Unloading Track" +msgstr "Abladungsgleis" + +#: advtrains_train_track/init.lua:342 +msgid "Loading Track" +msgstr "Beladungsgleis" + +#: advtrains_train_track/init.lua:406 +msgid "Detector Rail" +msgstr "Detektorgleis" + +#: advtrains_train_industrial/init.lua:10 +#: advtrains_train_industrial/init.lua:49 advtrains_train_steam/init.lua:20 +#: advtrains_train_steam/init.lua:91 +msgid "Driver Stand (right)" +msgstr "Führerstand Rechts" + +#: advtrains_train_industrial/init.lua:17 +#: advtrains_train_industrial/init.lua:56 advtrains_train_steam/init.lua:14 +#: advtrains_train_steam/init.lua:85 +msgid "Driver Stand (left)" +msgstr "Führerstand Links" + +#: advtrains_train_industrial/init.lua:40 +msgid "Industrial Train Engine" +msgstr "Industrielle Lokomotive" + +#: advtrains_train_industrial/init.lua:79 +msgid "Big Industrial Train Engine" +msgstr "Große Industrielle Lokomotive" + +#: advtrains_train_industrial/init.lua:98 +msgid "Industrial tank wagon" +msgstr "Tankwaggon" + +#: advtrains_train_industrial/init.lua:116 +msgid "Industrial wood wagon" +msgstr "Holztransportwaggon" + +#: advtrains_train_japan/init.lua:4 +msgid "Japanese Train Inter-Wagon Connection" +msgstr "Waggonzwischenverbindung Japanischer Personenzüge" + +#: advtrains_train_japan/init.lua:37 +msgid "Driver stand" +msgstr "Führerstand" + +#: advtrains_train_japan/init.lua:101 +msgid "Japanese Train Engine" +msgstr "Japanische Personenzug-Lokomotive" + +#: advtrains_train_japan/init.lua:176 +msgid "Japanese Train Wagon" +msgstr "Japanischer Personenzug-Passagierwaggon" + +#: advtrains_train_steam/init.lua:75 +msgid "Steam Engine" +msgstr "Dampflokomotive" + +#: advtrains_train_steam/init.lua:159 +msgid "Detailed Steam Engine" +msgstr "detaillierte Dampflokomotive" + +#: advtrains_train_steam/init.lua:206 +msgid "Passenger Wagon" +msgstr "Passagierwaggon" + +#: advtrains_train_steam/init.lua:226 +msgid "Box Wagon" +msgstr "Güterwaggon" + +#: advtrains_train_subway/init.lua:144 +msgid "Subway Passenger Wagon" +msgstr "U-Bahn-Waggon" + +#~ msgid "This position is protected!" +#~ msgstr "Diese Position ist geschützt!" + +#~ msgid "Can't place: protected position!" +#~ msgstr "Es kann nicht platziert werden: diese Position ist geschützt." + +#~ msgid "Deprecated Track" +#~ msgstr "ausrangiertes Gleis, nicht verwenden." + +#~ msgid "Can't get on: wagon full or doors closed!" +#~ msgstr "" +#~ "Sie können nicht einsteigen: der Waggon ist voll oder die Türen sind " +#~ "geschlossen." + +#~ msgid "Use Sneak+rightclick to bypass closed doors!" +#~ msgstr "" +#~ "Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen " +#~ "einzusteigen." + +#~ msgid "Access to @1" +#~ msgstr "Zugang zu @1" + +#~ msgid "" +#~ "ATC controller, mode @1\n" +#~ "Channel: @2" +#~ msgstr "" +#~ "Zugbeeinflussungsgleis in Betriebsart „@1“\n" +#~ "Kanal: @2" + +#~ msgid "Lock couples" +#~ msgstr "Kupplungen sperren" + +#~ msgid "" +#~ "You need to own at least one neighboring wagon to destroy this couple." +#~ msgstr "" +#~ "Sie müssen Besitzer eines angrenzenden Waggons sein, um hier abzukuppeln." + +#~ msgid "Speed:" +#~ msgstr "Geschw.:" + +#~ msgid "Target:" +#~ msgstr "Zielges.:" + +#~ msgid "Default Seat" +#~ msgstr "Standardsitzplatz" + +#~ msgid "Default Seat (driver stand)" +#~ msgstr "Standardsitzplatz (Führerstand)" diff --git a/advtrains/po/fr.po b/advtrains/po/fr.po new file mode 100644 index 0000000..9a16799 --- /dev/null +++ b/advtrains/po/fr.po @@ -0,0 +1,579 @@ +msgid "" +msgstr "" +"Project-Id-Version: advtrains\n" +"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" +"POT-Creation-Date: 2023-10-04 15:40+0200\n" +"PO-Revision-Date: 2022-07-05 10:11+0200\n" +"Last-Translator: Tanavit \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: advtrains/atc.lua:109 +msgid "ATC controller, unconfigured." +msgstr "Controlleur ATC, non-configuré " + +#: advtrains/atc.lua:150 +msgid "" +"ATC controller, mode @1\n" +"Command: @2" +msgstr "" +"Controlleur ATC, mode @1\n" +"Commande : @2" + +#: advtrains/atc.lua:180 +msgid "Command" +msgstr "Commande" + +#: advtrains/atc.lua:184 +msgid "Command (on)" +msgstr "Commande (marche) " + +#: advtrains/atc.lua:187 +msgid "Digiline channel" +msgstr "Canal Digiline" + +#: advtrains/atc.lua:189 advtrains_line_automation/stoprail.lua:65 +msgid "Save" +msgstr "Sauvegarder" + +#: advtrains/atc.lua:236 +msgid "ATC Reverse command warning: didn't reverse train, train moving!" +msgstr "" +"Attention : Commande ATC de renversement impossible car le train se déplace !" + +#: advtrains/atc.lua:248 +msgid "ATC Kick command warning: Doors closed" +msgstr "" + +#: advtrains/atc.lua:252 +msgid "ATC Kick command warning: Train moving" +msgstr "" + +#: advtrains/atc.lua:322 +msgid "ATC command syntax error: I statement not closed: @1" +msgstr "Erreur de syntaxe de commande ATC : instruction \"I\" incomplète : @1" + +#: advtrains/atc.lua:385 +msgid "ATC command parse error: Unknown command: @1" +msgstr "Erreur d'analyse de commande ATC : Commande inconnue : @1" + +#: advtrains/craft_items.lua:3 +msgid "Boiler" +msgstr "Chaudière à vapeur" + +#: advtrains/craft_items.lua:9 +msgid "driver's cab" +msgstr "Cabine de pilotage" + +#: advtrains/craft_items.lua:15 +msgid "Wheel" +msgstr "Roue" + +#: advtrains/craft_items.lua:21 +msgid "Chimney" +msgstr "Cheminée" + +#: advtrains/misc_nodes.lua:16 +msgid "@1 Platform (low)" +msgstr "Quai @1 (bas)" + +#: advtrains/misc_nodes.lua:33 +msgid "@1 Platform (high)" +msgstr "Quai @1 (haut)" + +#: advtrains/misc_nodes.lua:59 +msgid "@1 Platform (45 degree)" +msgstr "Quai @1 (haut, 45°)" + +#: advtrains/misc_nodes.lua:81 +msgid "@1 Platform (low, 45 degree)" +msgstr "Quai @1 (bas, 45°)" + +#: advtrains/trackplacer.lua:313 +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate rail/bumper/signal/etc." +msgstr "" +"Outil \"Trackworker\"\n" +"\n" +"Clic-Gauche : change le type de rail (droit/courbé/aiguillage)\n" +"\n" +"Clic-Droit : tourne le rail/butoir/signal/etc..." + +#: advtrains/trackplacer.lua:340 advtrains/trackplacer.lua:377 +msgid "This node can't be rotated using the trackworker!" +msgstr "Ce nœud ne peut être tourné avec l'outil \"Trackworker\" !" + +#: advtrains/trackplacer.lua:350 +msgid "This track can not be rotated!" +msgstr "Cette voie ne peut pas être tournée !" + +#: advtrains/trackplacer.lua:404 +msgid "This node can't be changed using the trackworker!" +msgstr "Ce nœud ne peut être modifié avec l'outil \"Trackworker\" !" + +#: advtrains/trackplacer.lua:414 +msgid "This track can not be changed!" +msgstr "Cette voie ne peut pas être modifiée !" + +#: advtrains/wagons.lua:179 +msgid "This wagon is owned by @1, you can't destroy it." +msgstr "Ce wagon est la propriété de @1, vous ne pouvez pas le détruire." + +#: advtrains/wagons.lua:203 +msgid "The wagon's inventory is not empty!" +msgstr "Le stock de ce wagon n'est pas vide !" + +#: advtrains/wagons.lua:210 +msgid "Wagon needs to be decoupled from other wagons in order to destroy it." +msgstr "" + +#: advtrains/wagons.lua:216 +msgid "" +"Warning: If you destroy this wagon, you only get some steel back! If you are " +"sure, hold Sneak and left-click the wagon." +msgstr "" +"Attention: Si vous détruisez ce wagon, vous ne récupérerez que de la " +"ferraille ! Si vous êtes sûr de vous, appuyez la touche \"Marcher lentement " +"(Sneak)\" et Clic-Gauche." + +#: advtrains/wagons.lua:649 advtrains/wagons.lua:850 +msgid "Show Inventory" +msgstr "Montrer le stock" + +#: advtrains/wagons.lua:652 +msgid "Onboard Computer" +msgstr "" + +#: advtrains/wagons.lua:655 advtrains/wagons.lua:1328 +msgid "Wagon properties" +msgstr "Propriétés du wagon" + +#: advtrains/wagons.lua:658 +msgid "Get off" +msgstr "Débarquer" + +#: advtrains/wagons.lua:661 +msgid "Get off (forced)" +msgstr "Débarquer (de force)" + +#: advtrains/wagons.lua:663 +msgid "(Doors closed)" +msgstr "(Portes closes)" + +#: advtrains/wagons.lua:712 +msgid "Can't get on: " +msgstr "" + +#: advtrains/wagons.lua:838 +msgid "Select seat:" +msgstr "Choisir le siège" + +#: advtrains/wagons.lua:880 +msgid "Save wagon properties" +msgstr "Sauvegarder les propriétés du wagon" + +#: advtrains/wagons.lua:965 +msgid "Text displayed outside on train" +msgstr "Texte affiché à l'extérieur du train" + +#: advtrains/wagons.lua:966 +msgid "Text displayed inside train" +msgstr "Texte affiché à l'intérieur du train" + +#: advtrains/wagons.lua:967 +msgid "Line" +msgstr "Ligne " + +#: advtrains/wagons.lua:968 +msgid "Routingcode" +msgstr "Code de routage" + +#: advtrains/wagons.lua:1241 +msgid "" +"Doors are closed! Use Sneak+rightclick to ignore the closed doors and get " +"off!" +msgstr "" +"Portes closes ! Utilisez \"Marcher lentement (Sneak)\" et Clic-Droit pour " +"franchir les portes et débarquer !" + +#: advtrains/trainhud.lua:305 +msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." +msgstr "" + +#: advtrains/tracks.lua:449 +msgid "This track can not be removed!" +msgstr "Cette voie ne peut pas être enlevée !" + +#: advtrains/tracks.lua:616 +msgid "Position is occupied by a train." +msgstr "Cet emplacement est occupé par un train." + +#: advtrains/tracks.lua:622 +msgid "There's a Track Circuit Break here." +msgstr "Il y a un \"Track Circuit Break\" ici." + +#: advtrains/tracks.lua:626 +msgid "There's a Signal Influence Point here." +msgstr "Il y a un \"Signal Influence Point\" ici." + +#: advtrains/tracks.lua:637 +msgid "@1 Slope" +msgstr "Pente @1" + +#: advtrains/tracks.lua:648 advtrains/tracks.lua:653 +msgid "Can't place: not pointing at node" +msgstr "Placement impossible : ne pointe pas un nœud" + +#: advtrains/tracks.lua:658 +msgid "Can't place: space occupied!" +msgstr "Placement impossible : espace occupé" + +#: advtrains/tracks.lua:711 +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "" +"Placement impossible : quantité insuffisante de voie pentue (@1 manquant)" + +#: advtrains/tracks.lua:714 +msgid "Can't place: There's no slope of length @1" +msgstr "Placement impossible : il n'y a pas de voie pentue de longueur @1" + +#: advtrains/tracks.lua:721 +msgid "Can't place: no supporting node at upper end." +msgstr "Placement impossible : pas de nœud d'appui à l'extrémité supérieure" + +#: advtrains/signals.lua:63 +msgid "Lampless Signal" +msgstr "Sémaphore" + +#: advtrains/signals.lua:127 +msgid "Signal" +msgstr "" + +#: advtrains/signals.lua:191 +msgid "Wallmounted Signal (l)" +msgstr "Signal mural (gauche)" + +#: advtrains/signals.lua:192 +msgid "Wallmounted Signal (r)" +msgstr "Signal mural (droit)" + +#: advtrains/signals.lua:193 +msgid "Wallmounted Signal (t)" +msgstr "Signal mural (plafond)" + +#: advtrains/signals.lua:281 advtrains/signals.lua:322 +msgid "Andrew's Cross" +msgstr "Croix de Saint André" + +#: advtrains/couple.lua:28 +msgid "Buffer and Chain Coupler" +msgstr "Attelage à tampon et vis" + +#: advtrains/couple.lua:29 +msgid "Scharfenberg Coupler" +msgstr "Attelage Scharfenberg" + +#: advtrains/couple.lua:185 +msgid "" +"You are not allowed to couple trains without the train_operator privilege." +msgstr "" + +#: advtrains/couple.lua:329 advtrains/couple.lua:333 +msgid "" +msgstr "" + +#: advtrains/couple.lua:334 +msgid "Can not couple: The couplers of the trains do not match (@1 and @2)." +msgstr "" +"Accouplement impossible: les attelages des trains ne concordent pas (@1 et " +"@2)." + +#: advtrains/copytool.lua:8 +msgid "" +"Train copy/paste tool\n" +"\n" +"Left-click: copy train\n" +"Right-click: paste train" +msgstr "" +"Outil de copie/collage de train\n" +"\n" +"Clic-Gauche : copie\n" +"\n" +"Clic-Droit : collage" + +#: advtrains/copytool.lua:29 +msgid "You do not have the @1 privilege." +msgstr "Vous ne possédez pas le privilège \"@1\"." + +#: advtrains/copytool.lua:41 +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "La voie sur laquelle vous tentez de placer le wagon est trop courte !" + +#: advtrains/copytool.lua:47 +msgid "The clipboard couldn't access the metadata. Paste failed." +msgstr "Le presse-papier ne peut accéder aux métadonnées. Échec du collage." + +#: advtrains/copytool.lua:52 advtrains/copytool.lua:57 +msgid "The clipboard is empty." +msgstr "Le presse-papier est vide." + +#: advtrains/copytool.lua:74 +msgid "Back of train would end up off track, cancelling." +msgstr "La fin du train serait hors voie : annulation." + +#: advtrains/copytool.lua:92 +msgid "No such lua entity!" +msgstr "Pas de telle entité lua !" + +#: advtrains/copytool.lua:98 +msgid "No such wagon: @1" +msgstr "Pas de tel wagon : @1" + +#: advtrains/copytool.lua:104 +msgid "No such train: @1" +msgstr "Pas de tel train : @1" + +#: advtrains/copytool.lua:176 +msgid "The clipboard couldn't access the metadata. Copy failed." +msgstr "Le presse-papier ne peut accéder aux métadonnées. Échec de la copie." + +#: advtrains/copytool.lua:180 +msgid "Train copied!" +msgstr "Train copié !" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build near tracks without the track_builder privilege." +msgstr "" +"Vous ne pouvez pas construire à proximité d'une voie sans le privilège " +"\"track_builder\" (?)" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build tracks without the track_builder privilege." +msgstr "" +"Vous ne pouvez pas construire une voie sans le privilège \"track_builder\"" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build near tracks at this protected position." +msgstr "" +"Vous ne pouvez pas construire à proximité d'une voie à cet emplacement " +"protégé" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build tracks at this protected position." +msgstr "Vous ne pouvez pas construire une voie à cet emplacement protégé" + +#: advtrains/protection.lua:184 +msgid "" +"You are not allowed to operate turnouts and signals without the " +"railway_operator privilege." +msgstr "" +"Vous ne pouvez pas actionner les aiguillages ou les signaux (privilège " +"\"railway_operator\" manquant)" + +#: advtrains_line_automation/stoprail.lua:54 +msgid "Station Code" +msgstr "Code de Station" + +#: advtrains_line_automation/stoprail.lua:55 +msgid "Station Name" +msgstr "Nom de Station" + +#: advtrains_line_automation/stoprail.lua:56 +msgid "Door Delay" +msgstr "Durée d'ouverture des portes" + +#: advtrains_line_automation/stoprail.lua:57 +msgid "Dep. Speed" +msgstr "Vitesse de départ" + +#: advtrains_line_automation/stoprail.lua:58 advtrains_train_track/init.lua:11 +#: advtrains_train_track/init.lua:156 +msgid "Track" +msgstr "Voie" + +#: advtrains_line_automation/stoprail.lua:59 +msgid "Stop Time" +msgstr "Durée d'arrêt" + +#: advtrains_line_automation/stoprail.lua:60 +msgid "Door Side" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:62 +msgid "Reverse train" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:63 +msgid "Kick out passengers" +msgstr "" + +#: advtrains_luaautomation/pcnaming.lua:26 +msgid "" +"Passive Component Naming Tool\n" +"\n" +"Right-click to name a passive component." +msgstr "" +"Outil de nommage de composant passif\n" +"\n" +"Clic-Droit pour nommer un composant passif." + +#: advtrains_train_track/init.lua:31 +msgid "Y-turnout" +msgstr "Embranchement en Y" + +#: advtrains_train_track/init.lua:49 +msgid "3-way turnout" +msgstr "Embranchement triple" + +#: advtrains_train_track/init.lua:69 +msgid "Perpendicular Diamond Crossing Track" +msgstr "Croisement perpendiculaire" + +#: advtrains_train_track/init.lua:91 +msgid "90+Angle Diamond Crossing Track" +msgstr "Croisement perpendiculo-diagonal" + +#: advtrains_train_track/init.lua:132 +msgid "Diagonal Diamond Crossing Track" +msgstr "Croisement diagonal" + +#: advtrains_train_track/init.lua:179 +msgid "Bumper" +msgstr "Heurtoir" + +#: advtrains_train_track/init.lua:201 +msgid "ATC controller" +msgstr "Controlleur ATC" + +#: advtrains_train_track/init.lua:317 +msgid "Unloading Track" +msgstr "Voie de Déchargement" + +#: advtrains_train_track/init.lua:342 +msgid "Loading Track" +msgstr "Voie de Chargement" + +#: advtrains_train_track/init.lua:406 +msgid "Detector Rail" +msgstr "Voie détectrice" + +#: advtrains_train_industrial/init.lua:10 +#: advtrains_train_industrial/init.lua:49 advtrains_train_steam/init.lua:20 +#: advtrains_train_steam/init.lua:91 +msgid "Driver Stand (right)" +msgstr "Poste de pilotage (droit)" + +#: advtrains_train_industrial/init.lua:17 +#: advtrains_train_industrial/init.lua:56 advtrains_train_steam/init.lua:14 +#: advtrains_train_steam/init.lua:85 +msgid "Driver Stand (left)" +msgstr "Poste de pilotage (gauche)" + +#: advtrains_train_industrial/init.lua:40 +msgid "Industrial Train Engine" +msgstr "Locomotive industrielle" + +#: advtrains_train_industrial/init.lua:79 +msgid "Big Industrial Train Engine" +msgstr "Grosse locomotive industrielle " + +#: advtrains_train_industrial/init.lua:98 +msgid "Industrial tank wagon" +msgstr "Wagon-citerne industriel" + +#: advtrains_train_industrial/init.lua:116 +msgid "Industrial wood wagon" +msgstr "Wagon grumier industriel" + +#: advtrains_train_japan/init.lua:4 +msgid "Japanese Train Inter-Wagon Connection" +msgstr "Passage inter-voiture de train Japonais" + +#: advtrains_train_japan/init.lua:37 +msgid "Driver stand" +msgstr "Poste de pilotage" + +#: advtrains_train_japan/init.lua:101 +msgid "Japanese Train Engine" +msgstr "Motrice Japonaise" + +#: advtrains_train_japan/init.lua:176 +msgid "Japanese Train Wagon" +msgstr "Voiture Japonaise" + +#: advtrains_train_steam/init.lua:75 +msgid "Steam Engine" +msgstr "Locomotive à vapeur" + +#: advtrains_train_steam/init.lua:159 +msgid "Detailed Steam Engine" +msgstr "Locomotive à vapeur complexe" + +#: advtrains_train_steam/init.lua:206 +msgid "Passenger Wagon" +msgstr "Voiture passager" + +#: advtrains_train_steam/init.lua:226 +msgid "Box Wagon" +msgstr "Wagon de frêt" + +#: advtrains_train_subway/init.lua:144 +msgid "Subway Passenger Wagon" +msgstr "Voiture de Métropolitain" + +#~ msgid "This position is protected!" +#~ msgstr "Cet emplacement est protégé !" + +#~ msgid "Can't place: protected position!" +#~ msgstr "Placement impossible : emplacement protégé" + +#~ msgid "Deprecated Track" +#~ msgstr "Voie déconseillée" + +#~ msgid "Can't get on: wagon full or doors closed!" +#~ msgstr "" +#~ "Embarquement impossible : le wagon est plein ou ses portes sont closes !" + +#~ msgid "Use Sneak+rightclick to bypass closed doors!" +#~ msgstr "" +#~ "Utilisez \"Marcher lentement (Sneak)\" et Clic-Droit pour franchir les " +#~ "portes closes !" + +#~ msgid "Access to @1" +#~ msgstr "Accès à @1" + +#~ msgid "" +#~ "ATC controller, mode @1\n" +#~ "Channel: @2" +#~ msgstr "" +#~ "Controlleur ATC, mode @1\n" +#~ "Canal : @2" + +#~ msgid "Lock couples" +#~ msgstr "Verrouiller l'accouplement" + +#~ msgid "" +#~ "You need to own at least one neighboring wagon to destroy this couple." +#~ msgstr "" +#~ "Vous devez être propriétaire d'au moins un wagon voisin pour supprimer " +#~ "cet attelage." + +#~ msgid "Speed:" +#~ msgstr "Vitesse : " + +#~ msgid "Target:" +#~ msgstr "Destination : " + +#~ msgid "Default Seat" +#~ msgstr "Siège par défaut" + +#~ msgid "Default Seat (driver stand)" +#~ msgstr "Siège par défaut (poste de pilotage)" diff --git a/advtrains/po/template.pot b/advtrains/po/template.pot new file mode 100644 index 0000000..23aaa6a --- /dev/null +++ b/advtrains/po/template.pot @@ -0,0 +1,505 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the advtrains package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: advtrains\n" +"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" +"POT-Creation-Date: 2023-10-04 15:40+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: advtrains/atc.lua:109 +msgid "ATC controller, unconfigured." +msgstr "" + +#: advtrains/atc.lua:150 +msgid "" +"ATC controller, mode @1\n" +"Command: @2" +msgstr "" + +#: advtrains/atc.lua:180 +msgid "Command" +msgstr "" + +#: advtrains/atc.lua:184 +msgid "Command (on)" +msgstr "" + +#: advtrains/atc.lua:187 +msgid "Digiline channel" +msgstr "" + +#: advtrains/atc.lua:189 advtrains_line_automation/stoprail.lua:65 +msgid "Save" +msgstr "" + +#: advtrains/atc.lua:236 +msgid "ATC Reverse command warning: didn't reverse train, train moving!" +msgstr "" + +#: advtrains/atc.lua:248 +msgid "ATC Kick command warning: Doors closed" +msgstr "" + +#: advtrains/atc.lua:252 +msgid "ATC Kick command warning: Train moving" +msgstr "" + +#: advtrains/atc.lua:322 +msgid "ATC command syntax error: I statement not closed: @1" +msgstr "" + +#: advtrains/atc.lua:385 +msgid "ATC command parse error: Unknown command: @1" +msgstr "" + +#: advtrains/craft_items.lua:3 +msgid "Boiler" +msgstr "" + +#: advtrains/craft_items.lua:9 +msgid "driver's cab" +msgstr "" + +#: advtrains/craft_items.lua:15 +msgid "Wheel" +msgstr "" + +#: advtrains/craft_items.lua:21 +msgid "Chimney" +msgstr "" + +#: advtrains/misc_nodes.lua:16 +msgid "@1 Platform (low)" +msgstr "" + +#: advtrains/misc_nodes.lua:33 +msgid "@1 Platform (high)" +msgstr "" + +#: advtrains/misc_nodes.lua:59 +msgid "@1 Platform (45 degree)" +msgstr "" + +#: advtrains/misc_nodes.lua:81 +msgid "@1 Platform (low, 45 degree)" +msgstr "" + +#: advtrains/trackplacer.lua:313 +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate rail/bumper/signal/etc." +msgstr "" + +#: advtrains/trackplacer.lua:340 advtrains/trackplacer.lua:377 +msgid "This node can't be rotated using the trackworker!" +msgstr "" + +#: advtrains/trackplacer.lua:350 +msgid "This track can not be rotated!" +msgstr "" + +#: advtrains/trackplacer.lua:404 +msgid "This node can't be changed using the trackworker!" +msgstr "" + +#: advtrains/trackplacer.lua:414 +msgid "This track can not be changed!" +msgstr "" + +#: advtrains/wagons.lua:179 +msgid "This wagon is owned by @1, you can't destroy it." +msgstr "" + +#: advtrains/wagons.lua:203 +msgid "The wagon's inventory is not empty!" +msgstr "" + +#: advtrains/wagons.lua:210 +msgid "Wagon needs to be decoupled from other wagons in order to destroy it." +msgstr "" + +#: advtrains/wagons.lua:216 +msgid "" +"Warning: If you destroy this wagon, you only get some steel back! If you are " +"sure, hold Sneak and left-click the wagon." +msgstr "" + +#: advtrains/wagons.lua:649 advtrains/wagons.lua:850 +msgid "Show Inventory" +msgstr "" + +#: advtrains/wagons.lua:652 +msgid "Onboard Computer" +msgstr "" + +#: advtrains/wagons.lua:655 advtrains/wagons.lua:1328 +msgid "Wagon properties" +msgstr "" + +#: advtrains/wagons.lua:658 +msgid "Get off" +msgstr "" + +#: advtrains/wagons.lua:661 +msgid "Get off (forced)" +msgstr "" + +#: advtrains/wagons.lua:663 +msgid "(Doors closed)" +msgstr "" + +#: advtrains/wagons.lua:712 +msgid "Can't get on: " +msgstr "" + +#: advtrains/wagons.lua:838 +msgid "Select seat:" +msgstr "" + +#: advtrains/wagons.lua:880 +msgid "Save wagon properties" +msgstr "" + +#: advtrains/wagons.lua:965 +msgid "Text displayed outside on train" +msgstr "" + +#: advtrains/wagons.lua:966 +msgid "Text displayed inside train" +msgstr "" + +#: advtrains/wagons.lua:967 +msgid "Line" +msgstr "" + +#: advtrains/wagons.lua:968 +msgid "Routingcode" +msgstr "" + +#: advtrains/wagons.lua:1241 +msgid "" +"Doors are closed! Use Sneak+rightclick to ignore the closed doors and get " +"off!" +msgstr "" + +#: advtrains/trainhud.lua:305 +msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." +msgstr "" + +#: advtrains/tracks.lua:449 +msgid "This track can not be removed!" +msgstr "" + +#: advtrains/tracks.lua:616 +msgid "Position is occupied by a train." +msgstr "" + +#: advtrains/tracks.lua:622 +msgid "There's a Track Circuit Break here." +msgstr "" + +#: advtrains/tracks.lua:626 +msgid "There's a Signal Influence Point here." +msgstr "" + +#: advtrains/tracks.lua:637 +msgid "@1 Slope" +msgstr "" + +#: advtrains/tracks.lua:648 advtrains/tracks.lua:653 +msgid "Can't place: not pointing at node" +msgstr "" + +#: advtrains/tracks.lua:658 +msgid "Can't place: space occupied!" +msgstr "" + +#: advtrains/tracks.lua:711 +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "" + +#: advtrains/tracks.lua:714 +msgid "Can't place: There's no slope of length @1" +msgstr "" + +#: advtrains/tracks.lua:721 +msgid "Can't place: no supporting node at upper end." +msgstr "" + +#: advtrains/signals.lua:63 +msgid "Lampless Signal" +msgstr "" + +#: advtrains/signals.lua:127 +msgid "Signal" +msgstr "" + +#: advtrains/signals.lua:191 +msgid "Wallmounted Signal (l)" +msgstr "" + +#: advtrains/signals.lua:192 +msgid "Wallmounted Signal (r)" +msgstr "" + +#: advtrains/signals.lua:193 +msgid "Wallmounted Signal (t)" +msgstr "" + +#: advtrains/signals.lua:281 advtrains/signals.lua:322 +msgid "Andrew's Cross" +msgstr "" + +#: advtrains/couple.lua:28 +msgid "Buffer and Chain Coupler" +msgstr "" + +#: advtrains/couple.lua:29 +msgid "Scharfenberg Coupler" +msgstr "" + +#: advtrains/couple.lua:185 +msgid "" +"You are not allowed to couple trains without the train_operator privilege." +msgstr "" + +#: advtrains/couple.lua:329 advtrains/couple.lua:333 +msgid "" +msgstr "" + +#: advtrains/couple.lua:334 +msgid "Can not couple: The couplers of the trains do not match (@1 and @2)." +msgstr "" + +#: advtrains/copytool.lua:8 +msgid "" +"Train copy/paste tool\n" +"\n" +"Left-click: copy train\n" +"Right-click: paste train" +msgstr "" + +#: advtrains/copytool.lua:29 +msgid "You do not have the @1 privilege." +msgstr "" + +#: advtrains/copytool.lua:41 +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "" + +#: advtrains/copytool.lua:47 +msgid "The clipboard couldn't access the metadata. Paste failed." +msgstr "" + +#: advtrains/copytool.lua:52 advtrains/copytool.lua:57 +msgid "The clipboard is empty." +msgstr "" + +#: advtrains/copytool.lua:74 +msgid "Back of train would end up off track, cancelling." +msgstr "" + +#: advtrains/copytool.lua:92 +msgid "No such lua entity!" +msgstr "" + +#: advtrains/copytool.lua:98 +msgid "No such wagon: @1" +msgstr "" + +#: advtrains/copytool.lua:104 +msgid "No such train: @1" +msgstr "" + +#: advtrains/copytool.lua:176 +msgid "The clipboard couldn't access the metadata. Copy failed." +msgstr "" + +#: advtrains/copytool.lua:180 +msgid "Train copied!" +msgstr "" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build near tracks without the track_builder privilege." +msgstr "" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build tracks without the track_builder privilege." +msgstr "" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build near tracks at this protected position." +msgstr "" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build tracks at this protected position." +msgstr "" + +#: advtrains/protection.lua:184 +msgid "" +"You are not allowed to operate turnouts and signals without the " +"railway_operator privilege." +msgstr "" + +#: advtrains_line_automation/stoprail.lua:54 +msgid "Station Code" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:55 +msgid "Station Name" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:56 +msgid "Door Delay" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:57 +msgid "Dep. Speed" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:58 advtrains_train_track/init.lua:11 +#: advtrains_train_track/init.lua:156 +msgid "Track" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:59 +msgid "Stop Time" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:60 +msgid "Door Side" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:62 +msgid "Reverse train" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:63 +msgid "Kick out passengers" +msgstr "" + +#: advtrains_luaautomation/pcnaming.lua:26 +msgid "" +"Passive Component Naming Tool\n" +"\n" +"Right-click to name a passive component." +msgstr "" + +#: advtrains_train_track/init.lua:31 +msgid "Y-turnout" +msgstr "" + +#: advtrains_train_track/init.lua:49 +msgid "3-way turnout" +msgstr "" + +#: advtrains_train_track/init.lua:69 +msgid "Perpendicular Diamond Crossing Track" +msgstr "" + +#: advtrains_train_track/init.lua:91 +msgid "90+Angle Diamond Crossing Track" +msgstr "" + +#: advtrains_train_track/init.lua:132 +msgid "Diagonal Diamond Crossing Track" +msgstr "" + +#: advtrains_train_track/init.lua:179 +msgid "Bumper" +msgstr "" + +#: advtrains_train_track/init.lua:201 +msgid "ATC controller" +msgstr "" + +#: advtrains_train_track/init.lua:317 +msgid "Unloading Track" +msgstr "" + +#: advtrains_train_track/init.lua:342 +msgid "Loading Track" +msgstr "" + +#: advtrains_train_track/init.lua:406 +msgid "Detector Rail" +msgstr "" + +#: advtrains_train_industrial/init.lua:10 +#: advtrains_train_industrial/init.lua:49 advtrains_train_steam/init.lua:20 +#: advtrains_train_steam/init.lua:91 +msgid "Driver Stand (right)" +msgstr "" + +#: advtrains_train_industrial/init.lua:17 +#: advtrains_train_industrial/init.lua:56 advtrains_train_steam/init.lua:14 +#: advtrains_train_steam/init.lua:85 +msgid "Driver Stand (left)" +msgstr "" + +#: advtrains_train_industrial/init.lua:40 +msgid "Industrial Train Engine" +msgstr "" + +#: advtrains_train_industrial/init.lua:79 +msgid "Big Industrial Train Engine" +msgstr "" + +#: advtrains_train_industrial/init.lua:98 +msgid "Industrial tank wagon" +msgstr "" + +#: advtrains_train_industrial/init.lua:116 +msgid "Industrial wood wagon" +msgstr "" + +#: advtrains_train_japan/init.lua:4 +msgid "Japanese Train Inter-Wagon Connection" +msgstr "" + +#: advtrains_train_japan/init.lua:37 +msgid "Driver stand" +msgstr "" + +#: advtrains_train_japan/init.lua:101 +msgid "Japanese Train Engine" +msgstr "" + +#: advtrains_train_japan/init.lua:176 +msgid "Japanese Train Wagon" +msgstr "" + +#: advtrains_train_steam/init.lua:75 +msgid "Steam Engine" +msgstr "" + +#: advtrains_train_steam/init.lua:159 +msgid "Detailed Steam Engine" +msgstr "" + +#: advtrains_train_steam/init.lua:206 +msgid "Passenger Wagon" +msgstr "" + +#: advtrains_train_steam/init.lua:226 +msgid "Box Wagon" +msgstr "" + +#: advtrains_train_subway/init.lua:144 +msgid "Subway Passenger Wagon" +msgstr "" diff --git a/advtrains/po/update-translations.sh b/advtrains/po/update-translations.sh new file mode 100755 index 0000000..d86c568 --- /dev/null +++ b/advtrains/po/update-translations.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# NOTE: Please make sure you also have basic_trains installed, as it uses attrans for historical reasons + +ATDIR=`dirname "$0"`/../.. +BTDIR="$ATDIR"/../basic_trains + +xgettext \ + -D "$ATDIR" \ + -D "$BTDIR" \ + -d advtrains \ + -p . \ + -L lua \ + --from-code=UTF-8 \ + --keyword='attrans' \ + --keyword='S' \ + --package-name='advtrains' \ + --msgid-bugs-address='advtrains-discuss@lists.sr.ht' \ + `find $ATDIR $BTDIR -name '*.lua' -printf '%P\n'` \ + && +mv advtrains.po template.pot && +for i in *.po; do + msgmerge -U \ + $i template.pot +done diff --git a/advtrains/po/zh_CN.po b/advtrains/po/zh_CN.po new file mode 100644 index 0000000..c81cf6c --- /dev/null +++ b/advtrains/po/zh_CN.po @@ -0,0 +1,560 @@ +msgid "" +msgstr "" +"Project-Id-Version: advtrains\n" +"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" +"POT-Creation-Date: 2023-10-04 15:40+0200\n" +"PO-Revision-Date: 2022-11-02 15:08+0100\n" +"Last-Translator: Y. Wang \n" +"Language-Team: Chinese (Simplified)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: advtrains/atc.lua:109 +msgid "ATC controller, unconfigured." +msgstr "ATC 控制器 (未配置)" + +#: advtrains/atc.lua:150 +msgid "" +"ATC controller, mode @1\n" +"Command: @2" +msgstr "" +"ATC 控制器\n" +"模式:@1\n" +"命令:@2" + +#: advtrains/atc.lua:180 +msgid "Command" +msgstr "命令" + +#: advtrains/atc.lua:184 +msgid "Command (on)" +msgstr "命令 (激活时)" + +#: advtrains/atc.lua:187 +msgid "Digiline channel" +msgstr "Digiline 频道" + +#: advtrains/atc.lua:189 advtrains_line_automation/stoprail.lua:65 +msgid "Save" +msgstr "保存" + +#: advtrains/atc.lua:236 +msgid "ATC Reverse command warning: didn't reverse train, train moving!" +msgstr "ATC 警告:未执行“R”命令,火车在移动" + +#: advtrains/atc.lua:248 +msgid "ATC Kick command warning: Doors closed" +msgstr "" + +#: advtrains/atc.lua:252 +msgid "ATC Kick command warning: Train moving" +msgstr "" + +#: advtrains/atc.lua:322 +msgid "ATC command syntax error: I statement not closed: @1" +msgstr "ATC 语法错误:“I”命令不完整:@1" + +#: advtrains/atc.lua:385 +msgid "ATC command parse error: Unknown command: @1" +msgstr "ATC 语法错误:未知命令:@1" + +#: advtrains/craft_items.lua:3 +msgid "Boiler" +msgstr "锅炉" + +#: advtrains/craft_items.lua:9 +msgid "driver's cab" +msgstr "驾驶室" + +#: advtrains/craft_items.lua:15 +msgid "Wheel" +msgstr "车轮" + +#: advtrains/craft_items.lua:21 +msgid "Chimney" +msgstr "烟囱" + +#: advtrains/misc_nodes.lua:16 +msgid "@1 Platform (low)" +msgstr "较低的@1站台" + +#: advtrains/misc_nodes.lua:33 +msgid "@1 Platform (high)" +msgstr "较高的@1站台" + +#: advtrains/misc_nodes.lua:59 +msgid "@1 Platform (45 degree)" +msgstr "较高的@1站台 (45°)" + +#: advtrains/misc_nodes.lua:81 +msgid "@1 Platform (low, 45 degree)" +msgstr "较低的@1站台 (45°)" + +#: advtrains/trackplacer.lua:313 +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate rail/bumper/signal/etc." +msgstr "" +"铁路调整工具\n" +"\n" +"左键单击:切换轨道类型\n" +"右键单击:旋转方块" + +#: advtrains/trackplacer.lua:340 advtrains/trackplacer.lua:377 +msgid "This node can't be rotated using the trackworker!" +msgstr "您不能使用铁路调整工具旋转这个方块。" + +#: advtrains/trackplacer.lua:350 +msgid "This track can not be rotated!" +msgstr "您不能旋转这段轨道。" + +#: advtrains/trackplacer.lua:404 +msgid "This node can't be changed using the trackworker!" +msgstr "您不能使用铁路调整工具调整这个方块。" + +#: advtrains/trackplacer.lua:414 +msgid "This track can not be changed!" +msgstr "您不能调整这段轨道。" + +#: advtrains/wagons.lua:179 +msgid "This wagon is owned by @1, you can't destroy it." +msgstr "这是 @1 的车厢,您不能摧毁它。" + +#: advtrains/wagons.lua:203 +msgid "The wagon's inventory is not empty!" +msgstr "" + +#: advtrains/wagons.lua:210 +msgid "Wagon needs to be decoupled from other wagons in order to destroy it." +msgstr "" + +#: advtrains/wagons.lua:216 +msgid "" +"Warning: If you destroy this wagon, you only get some steel back! If you are " +"sure, hold Sneak and left-click the wagon." +msgstr "" +"警告:如果您摧毁此车厢,您只能拿到一些钢方块。如果您确定要摧毁这节车厢,请按" +"潜行键并左键单击此车厢。" + +#: advtrains/wagons.lua:649 advtrains/wagons.lua:850 +msgid "Show Inventory" +msgstr "显示物品栏" + +#: advtrains/wagons.lua:652 +msgid "Onboard Computer" +msgstr "" + +#: advtrains/wagons.lua:655 advtrains/wagons.lua:1328 +msgid "Wagon properties" +msgstr "车厢属性" + +#: advtrains/wagons.lua:658 +msgid "Get off" +msgstr "下车" + +#: advtrains/wagons.lua:661 +msgid "Get off (forced)" +msgstr "强制下车" + +#: advtrains/wagons.lua:663 +msgid "(Doors closed)" +msgstr "(车门已关闭)" + +#: advtrains/wagons.lua:712 +msgid "Can't get on: " +msgstr "" + +#: advtrains/wagons.lua:838 +msgid "Select seat:" +msgstr "请选择座位" + +#: advtrains/wagons.lua:880 +msgid "Save wagon properties" +msgstr "保存车厢属性" + +#: advtrains/wagons.lua:965 +msgid "Text displayed outside on train" +msgstr "车厢外部显示" + +#: advtrains/wagons.lua:966 +msgid "Text displayed inside train" +msgstr "车厢内部显示" + +#: advtrains/wagons.lua:967 +msgid "Line" +msgstr "火车线路" + +#: advtrains/wagons.lua:968 +msgid "Routingcode" +msgstr "路由码" + +#: advtrains/wagons.lua:1241 +msgid "" +"Doors are closed! Use Sneak+rightclick to ignore the closed doors and get " +"off!" +msgstr "车门已关闭,请使用潜行+右键单击下车。" + +#: advtrains/trainhud.lua:305 +msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." +msgstr "" + +#: advtrains/tracks.lua:449 +msgid "This track can not be removed!" +msgstr "您不能移除这段轨道。" + +#: advtrains/tracks.lua:616 +msgid "Position is occupied by a train." +msgstr "" + +#: advtrains/tracks.lua:622 +msgid "There's a Track Circuit Break here." +msgstr "" + +#: advtrains/tracks.lua:626 +msgid "There's a Signal Influence Point here." +msgstr "" + +#: advtrains/tracks.lua:637 +msgid "@1 Slope" +msgstr "@1斜坡" + +#: advtrains/tracks.lua:648 advtrains/tracks.lua:653 +msgid "Can't place: not pointing at node" +msgstr "无法放置:您没有选择任何方块。" + +#: advtrains/tracks.lua:658 +msgid "Can't place: space occupied!" +msgstr "无法放置:此区域已被占用。" + +#: advtrains/tracks.lua:711 +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "无法放置:您没有足够的铁路斜坡放置工具 (您总共需要@1个)" + +#: advtrains/tracks.lua:714 +msgid "Can't place: There's no slope of length @1" +msgstr "无法放置:advtrains 不支持长度为@1米的斜坡。" + +#: advtrains/tracks.lua:721 +msgid "Can't place: no supporting node at upper end." +msgstr "无法放置:较高端没有支撑方块。" + +#: advtrains/signals.lua:63 +msgid "Lampless Signal" +msgstr "臂板信号机" + +#: advtrains/signals.lua:127 +msgid "Signal" +msgstr "信号灯" + +#: advtrains/signals.lua:191 +msgid "Wallmounted Signal (l)" +msgstr "壁挂式信号灯 (左侧)" + +#: advtrains/signals.lua:192 +msgid "Wallmounted Signal (r)" +msgstr "壁挂式信号灯 (右侧)" + +#: advtrains/signals.lua:193 +msgid "Wallmounted Signal (t)" +msgstr "悬挂式信号灯" + +#: advtrains/signals.lua:281 advtrains/signals.lua:322 +msgid "Andrew's Cross" +msgstr "铁路道口信号灯" + +#: advtrains/couple.lua:28 +msgid "Buffer and Chain Coupler" +msgstr "链式车钩" + +#: advtrains/couple.lua:29 +msgid "Scharfenberg Coupler" +msgstr "Scharfenberg 式车钩" + +#: advtrains/couple.lua:185 +msgid "" +"You are not allowed to couple trains without the train_operator privilege." +msgstr "您没有“train_operator”权限,不能连接这两节车厢。" + +#: advtrains/couple.lua:329 advtrains/couple.lua:333 +msgid "" +msgstr "" + +#: advtrains/couple.lua:334 +msgid "Can not couple: The couplers of the trains do not match (@1 and @2)." +msgstr "您无法连接这两节车厢:这两节车厢使用不同的车钩 (@1和@2)。" + +#: advtrains/copytool.lua:8 +msgid "" +"Train copy/paste tool\n" +"\n" +"Left-click: copy train\n" +"Right-click: paste train" +msgstr "" +"火车复制工具\n" +"\n" +"左键单击:复制\n" +"右键单击:粘帖" + +#: advtrains/copytool.lua:29 +msgid "You do not have the @1 privilege." +msgstr "您没有“@1”权限。" + +#: advtrains/copytool.lua:41 +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "轨道太短。" + +#: advtrains/copytool.lua:47 +msgid "The clipboard couldn't access the metadata. Paste failed." +msgstr "无法粘贴:剪贴板无法访问元数据。" + +#: advtrains/copytool.lua:52 advtrains/copytool.lua:57 +msgid "The clipboard is empty." +msgstr "剪贴板是空的。" + +#: advtrains/copytool.lua:74 +msgid "Back of train would end up off track, cancelling." +msgstr "火车后部不在轨道上。" + +#: advtrains/copytool.lua:92 +msgid "No such lua entity!" +msgstr "您没有指向一个可以用火车复制工具复制的物体。" + +#: advtrains/copytool.lua:98 +msgid "No such wagon: @1" +msgstr "ID 为“@1”的车厢不存在。" + +#: advtrains/copytool.lua:104 +msgid "No such train: @1" +msgstr "ID 为“@1”的列车不存在。" + +#: advtrains/copytool.lua:176 +msgid "The clipboard couldn't access the metadata. Copy failed." +msgstr "无法复制:剪贴板无法访问元数据。" + +#: advtrains/copytool.lua:180 +msgid "Train copied!" +msgstr "已复制" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build near tracks without the track_builder privilege." +msgstr "您没有“train_operator”权限,不能在铁路附近建任何东西。" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build tracks without the track_builder privilege." +msgstr "您没有“train_operator”权限,不能在这里建造铁路。" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build near tracks at this protected position." +msgstr "这里已被保护,您不能在这里的铁路附近建任何东西。" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build tracks at this protected position." +msgstr "这里已被保护,您不能在这里建造铁路。" + +#: advtrains/protection.lua:184 +msgid "" +"You are not allowed to operate turnouts and signals without the " +"railway_operator privilege." +msgstr "您没有“railway_operator”权限,不能控制铁路设施。" + +#: advtrains_line_automation/stoprail.lua:54 +msgid "Station Code" +msgstr "车站代码" + +#: advtrains_line_automation/stoprail.lua:55 +msgid "Station Name" +msgstr "车站名称" + +#: advtrains_line_automation/stoprail.lua:56 +msgid "Door Delay" +msgstr "车门关闭时间" + +#: advtrains_line_automation/stoprail.lua:57 +msgid "Dep. Speed" +msgstr "出发速度" + +#: advtrains_line_automation/stoprail.lua:58 advtrains_train_track/init.lua:11 +#: advtrains_train_track/init.lua:156 +msgid "Track" +msgstr "轨道" + +#: advtrains_line_automation/stoprail.lua:59 +msgid "Stop Time" +msgstr "停站时间" + +#: advtrains_line_automation/stoprail.lua:60 +msgid "Door Side" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:62 +msgid "Reverse train" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:63 +msgid "Kick out passengers" +msgstr "" + +#: advtrains_luaautomation/pcnaming.lua:26 +msgid "" +"Passive Component Naming Tool\n" +"\n" +"Right-click to name a passive component." +msgstr "" +"被动元件命名工具\n" +"\n" +"右键单击命名所选元件" + +#: advtrains_train_track/init.lua:31 +msgid "Y-turnout" +msgstr "对称道岔" + +#: advtrains_train_track/init.lua:49 +msgid "3-way turnout" +msgstr "三开道岔" + +#: advtrains_train_track/init.lua:69 +msgid "Perpendicular Diamond Crossing Track" +msgstr "垂直交叉轨道" + +#: advtrains_train_track/init.lua:91 +msgid "90+Angle Diamond Crossing Track" +msgstr "交叉轨道 (其中一条轨道与坐标轴平行)" + +#: advtrains_train_track/init.lua:132 +msgid "Diagonal Diamond Crossing Track" +msgstr "交叉轨道" + +#: advtrains_train_track/init.lua:179 +msgid "Bumper" +msgstr "保险杠" + +#: advtrains_train_track/init.lua:201 +msgid "ATC controller" +msgstr "ATC 控制器" + +#: advtrains_train_track/init.lua:317 +msgid "Unloading Track" +msgstr "卸货轨道" + +#: advtrains_train_track/init.lua:342 +msgid "Loading Track" +msgstr "装货轨道" + +#: advtrains_train_track/init.lua:406 +msgid "Detector Rail" +msgstr "探测轨道" + +#: advtrains_train_industrial/init.lua:10 +#: advtrains_train_industrial/init.lua:49 advtrains_train_steam/init.lua:20 +#: advtrains_train_steam/init.lua:91 +msgid "Driver Stand (right)" +msgstr "右侧司机座位" + +#: advtrains_train_industrial/init.lua:17 +#: advtrains_train_industrial/init.lua:56 advtrains_train_steam/init.lua:14 +#: advtrains_train_steam/init.lua:85 +msgid "Driver Stand (left)" +msgstr "左侧司机座位" + +#: advtrains_train_industrial/init.lua:40 +msgid "Industrial Train Engine" +msgstr "工业用火车头" + +#: advtrains_train_industrial/init.lua:79 +msgid "Big Industrial Train Engine" +msgstr "大型工业用火车头" + +#: advtrains_train_industrial/init.lua:98 +msgid "Industrial tank wagon" +msgstr "液体运输车厢" + +#: advtrains_train_industrial/init.lua:116 +msgid "Industrial wood wagon" +msgstr "木材运输车厢" + +#: advtrains_train_japan/init.lua:4 +msgid "Japanese Train Inter-Wagon Connection" +msgstr "日本火车车钩" + +#: advtrains_train_japan/init.lua:37 +msgid "Driver stand" +msgstr "司机座位" + +#: advtrains_train_japan/init.lua:101 +msgid "Japanese Train Engine" +msgstr "高速列车车头" + +#: advtrains_train_japan/init.lua:176 +msgid "Japanese Train Wagon" +msgstr "高速列车车厢" + +#: advtrains_train_steam/init.lua:75 +msgid "Steam Engine" +msgstr "蒸汽机车" + +#: advtrains_train_steam/init.lua:159 +msgid "Detailed Steam Engine" +msgstr "精细的蒸汽机车" + +#: advtrains_train_steam/init.lua:206 +msgid "Passenger Wagon" +msgstr "客车" + +#: advtrains_train_steam/init.lua:226 +msgid "Box Wagon" +msgstr "货运车厢" + +#: advtrains_train_subway/init.lua:144 +msgid "Subway Passenger Wagon" +msgstr "地铁车厢" + +#~ msgid "This position is protected!" +#~ msgstr "这里已被保护。" + +#~ msgid "Can't place: protected position!" +#~ msgstr "无法放置:此区域已被保护。" + +#~ msgid "Deprecated Track" +#~ msgstr "请不要使用" + +#~ msgid "Can't get on: wagon full or doors closed!" +#~ msgstr "无法上车:车门已关闭或车厢已满。" + +#~ msgid "Use Sneak+rightclick to bypass closed doors!" +#~ msgstr "请使用潜行+右键上车。" + +#~ msgid "Access to @1" +#~ msgstr "可前往@1" + +#~ msgid "" +#~ "ATC controller, mode @1\n" +#~ "Channel: @2" +#~ msgstr "" +#~ "ATC 控制器\n" +#~ "模式:@1\n" +#~ "频道:@2" + +#~ msgid "Lock couples" +#~ msgstr "锁定连接处" + +#~ msgid "" +#~ "You need to own at least one neighboring wagon to destroy this couple." +#~ msgstr "您必须至少拥有其中一节车厢才能分开这两节车厢。" + +#~ msgid "Speed:" +#~ msgstr "速度" + +#~ msgid "Target:" +#~ msgstr "目标速度" + +#~ msgid "Default Seat" +#~ msgstr "默认座位" + +#~ msgid "Default Seat (driver stand)" +#~ msgstr "默认座位 (司机座位)" diff --git a/advtrains/po/zh_TW.po b/advtrains/po/zh_TW.po new file mode 100644 index 0000000..91a205f --- /dev/null +++ b/advtrains/po/zh_TW.po @@ -0,0 +1,560 @@ +msgid "" +msgstr "" +"Project-Id-Version: advtrains\n" +"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" +"POT-Creation-Date: 2023-10-04 15:40+0200\n" +"PO-Revision-Date: 2022-11-02 15:08+0100\n" +"Last-Translator: Y. Wang \n" +"Language-Team: Chinese (Traditional)\n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: advtrains/atc.lua:109 +msgid "ATC controller, unconfigured." +msgstr "ATC 控制器 (未配置)" + +#: advtrains/atc.lua:150 +msgid "" +"ATC controller, mode @1\n" +"Command: @2" +msgstr "" +"ATC 控制器\n" +"模式:@1\n" +"命令:@2" + +#: advtrains/atc.lua:180 +msgid "Command" +msgstr "命令" + +#: advtrains/atc.lua:184 +msgid "Command (on)" +msgstr "命令 (啟用時)" + +#: advtrains/atc.lua:187 +msgid "Digiline channel" +msgstr "Digiline 頻道" + +#: advtrains/atc.lua:189 advtrains_line_automation/stoprail.lua:65 +msgid "Save" +msgstr "儲存" + +#: advtrains/atc.lua:236 +msgid "ATC Reverse command warning: didn't reverse train, train moving!" +msgstr "ATC 警告:未執行「R」命令,火車在移動" + +#: advtrains/atc.lua:248 +msgid "ATC Kick command warning: Doors closed" +msgstr "" + +#: advtrains/atc.lua:252 +msgid "ATC Kick command warning: Train moving" +msgstr "" + +#: advtrains/atc.lua:322 +msgid "ATC command syntax error: I statement not closed: @1" +msgstr "ATC 語法錯誤:「I」命令不完整:@1" + +#: advtrains/atc.lua:385 +msgid "ATC command parse error: Unknown command: @1" +msgstr "ATC 語法錯誤:未知命令:@1" + +#: advtrains/craft_items.lua:3 +msgid "Boiler" +msgstr "鍋爐" + +#: advtrains/craft_items.lua:9 +msgid "driver's cab" +msgstr "駕駛室" + +#: advtrains/craft_items.lua:15 +msgid "Wheel" +msgstr "車輪" + +#: advtrains/craft_items.lua:21 +msgid "Chimney" +msgstr "煙囪" + +#: advtrains/misc_nodes.lua:16 +msgid "@1 Platform (low)" +msgstr "較低的@1月臺" + +#: advtrains/misc_nodes.lua:33 +msgid "@1 Platform (high)" +msgstr "較高的@1月臺" + +#: advtrains/misc_nodes.lua:59 +msgid "@1 Platform (45 degree)" +msgstr "較高的@1月臺 (45°)" + +#: advtrains/misc_nodes.lua:81 +msgid "@1 Platform (low, 45 degree)" +msgstr "較低的@1月臺 (45°)" + +#: advtrains/trackplacer.lua:313 +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate rail/bumper/signal/etc." +msgstr "" +"鐵路調整工具\n" +"\n" +"左鍵單擊:切換軌道型別\n" +"右鍵單擊:旋轉方塊" + +#: advtrains/trackplacer.lua:340 advtrains/trackplacer.lua:377 +msgid "This node can't be rotated using the trackworker!" +msgstr "您不能使用鐵路調整工具旋轉這個方塊。" + +#: advtrains/trackplacer.lua:350 +msgid "This track can not be rotated!" +msgstr "您不能旋轉這段軌道。" + +#: advtrains/trackplacer.lua:404 +msgid "This node can't be changed using the trackworker!" +msgstr "您不能使用鐵路調整工具調整這個方塊。" + +#: advtrains/trackplacer.lua:414 +msgid "This track can not be changed!" +msgstr "您不能調整這段軌道。" + +#: advtrains/wagons.lua:179 +msgid "This wagon is owned by @1, you can't destroy it." +msgstr "這是 @1 的車廂,您不能摧毀它。" + +#: advtrains/wagons.lua:203 +msgid "The wagon's inventory is not empty!" +msgstr "" + +#: advtrains/wagons.lua:210 +msgid "Wagon needs to be decoupled from other wagons in order to destroy it." +msgstr "" + +#: advtrains/wagons.lua:216 +msgid "" +"Warning: If you destroy this wagon, you only get some steel back! If you are " +"sure, hold Sneak and left-click the wagon." +msgstr "" +"警告:如果您摧毀此車廂,您只能拿到一些鋼方塊。如果您確定要摧毀這節車廂,請按" +"潛行鍵並左鍵單擊此車廂。" + +#: advtrains/wagons.lua:649 advtrains/wagons.lua:850 +msgid "Show Inventory" +msgstr "顯示物品欄" + +#: advtrains/wagons.lua:652 +msgid "Onboard Computer" +msgstr "" + +#: advtrains/wagons.lua:655 advtrains/wagons.lua:1328 +msgid "Wagon properties" +msgstr "車廂屬性" + +#: advtrains/wagons.lua:658 +msgid "Get off" +msgstr "下車" + +#: advtrains/wagons.lua:661 +msgid "Get off (forced)" +msgstr "強制下車" + +#: advtrains/wagons.lua:663 +msgid "(Doors closed)" +msgstr "(車門已關閉)" + +#: advtrains/wagons.lua:712 +msgid "Can't get on: " +msgstr "" + +#: advtrains/wagons.lua:838 +msgid "Select seat:" +msgstr "請選擇座位" + +#: advtrains/wagons.lua:880 +msgid "Save wagon properties" +msgstr "儲存車廂屬性" + +#: advtrains/wagons.lua:965 +msgid "Text displayed outside on train" +msgstr "車廂外部顯示" + +#: advtrains/wagons.lua:966 +msgid "Text displayed inside train" +msgstr "車廂內部顯示" + +#: advtrains/wagons.lua:967 +msgid "Line" +msgstr "火車線路" + +#: advtrains/wagons.lua:968 +msgid "Routingcode" +msgstr "路由碼" + +#: advtrains/wagons.lua:1241 +msgid "" +"Doors are closed! Use Sneak+rightclick to ignore the closed doors and get " +"off!" +msgstr "車門已關閉,請使用潛行+右鍵單擊下車。" + +#: advtrains/trainhud.lua:305 +msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." +msgstr "" + +#: advtrains/tracks.lua:449 +msgid "This track can not be removed!" +msgstr "您不能移除這段軌道。" + +#: advtrains/tracks.lua:616 +msgid "Position is occupied by a train." +msgstr "" + +#: advtrains/tracks.lua:622 +msgid "There's a Track Circuit Break here." +msgstr "" + +#: advtrains/tracks.lua:626 +msgid "There's a Signal Influence Point here." +msgstr "" + +#: advtrains/tracks.lua:637 +msgid "@1 Slope" +msgstr "@1斜坡" + +#: advtrains/tracks.lua:648 advtrains/tracks.lua:653 +msgid "Can't place: not pointing at node" +msgstr "無法放置:您沒有選擇任何方塊。" + +#: advtrains/tracks.lua:658 +msgid "Can't place: space occupied!" +msgstr "無法放置:此區域已被佔用。" + +#: advtrains/tracks.lua:711 +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "無法放置:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個)" + +#: advtrains/tracks.lua:714 +msgid "Can't place: There's no slope of length @1" +msgstr "無法放置:advtrains 不支援長度為@1米的斜坡。" + +#: advtrains/tracks.lua:721 +msgid "Can't place: no supporting node at upper end." +msgstr "無法放置:較高階沒有支撐方塊。" + +#: advtrains/signals.lua:63 +msgid "Lampless Signal" +msgstr "臂木式號誌機" + +#: advtrains/signals.lua:127 +msgid "Signal" +msgstr "色燈號誌機" + +#: advtrains/signals.lua:191 +msgid "Wallmounted Signal (l)" +msgstr "壁掛式色燈號誌機 (左側)" + +#: advtrains/signals.lua:192 +msgid "Wallmounted Signal (r)" +msgstr "壁掛式色燈號誌機 (右側)" + +#: advtrains/signals.lua:193 +msgid "Wallmounted Signal (t)" +msgstr "懸掛式色燈號誌機" + +#: advtrains/signals.lua:281 advtrains/signals.lua:322 +msgid "Andrew's Cross" +msgstr "平交道號誌燈" + +#: advtrains/couple.lua:28 +msgid "Buffer and Chain Coupler" +msgstr "鏈式連結器" + +#: advtrains/couple.lua:29 +msgid "Scharfenberg Coupler" +msgstr "Scharfenberg 式連結器" + +#: advtrains/couple.lua:185 +msgid "" +"You are not allowed to couple trains without the train_operator privilege." +msgstr "您沒有「train_operator」許可權,不能連結這兩節車廂。" + +#: advtrains/couple.lua:329 advtrains/couple.lua:333 +msgid "" +msgstr "" + +#: advtrains/couple.lua:334 +msgid "Can not couple: The couplers of the trains do not match (@1 and @2)." +msgstr "您無法連結這兩節車廂:這兩節車廂使用不同的連結器 (@1和@2)。" + +#: advtrains/copytool.lua:8 +msgid "" +"Train copy/paste tool\n" +"\n" +"Left-click: copy train\n" +"Right-click: paste train" +msgstr "" +"火車複製工具\n" +"\n" +"左鍵單擊:複製\n" +"右鍵單擊:粘帖" + +#: advtrains/copytool.lua:29 +msgid "You do not have the @1 privilege." +msgstr "您沒有「@1」許可權。" + +#: advtrains/copytool.lua:41 +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "軌道太短。" + +#: advtrains/copytool.lua:47 +msgid "The clipboard couldn't access the metadata. Paste failed." +msgstr "無法貼上:剪貼簿無法訪問元資料。" + +#: advtrains/copytool.lua:52 advtrains/copytool.lua:57 +msgid "The clipboard is empty." +msgstr "剪貼簿是空的。" + +#: advtrains/copytool.lua:74 +msgid "Back of train would end up off track, cancelling." +msgstr "火車後部不在軌道上。" + +#: advtrains/copytool.lua:92 +msgid "No such lua entity!" +msgstr "您沒有指向一個可以用火車複製工具複製的物體。" + +#: advtrains/copytool.lua:98 +msgid "No such wagon: @1" +msgstr "ID 為「@1」的車廂不存在。" + +#: advtrains/copytool.lua:104 +msgid "No such train: @1" +msgstr "ID 為「@1」的列車不存在。" + +#: advtrains/copytool.lua:176 +msgid "The clipboard couldn't access the metadata. Copy failed." +msgstr "無法複製:剪貼簿無法訪問元資料。" + +#: advtrains/copytool.lua:180 +msgid "Train copied!" +msgstr "已複製" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build near tracks without the track_builder privilege." +msgstr "您沒有「train_operator」許可權,不能在鐵路附近建任何東西。" + +#: advtrains/protection.lua:148 +msgid "" +"You are not allowed to build tracks without the track_builder privilege." +msgstr "您沒有「train_operator」許可權,不能在這裡建造鐵路。" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build near tracks at this protected position." +msgstr "這裡已被保護,您不能在這裡的鐵路附近建任何東西。" + +#: advtrains/protection.lua:153 +msgid "You are not allowed to build tracks at this protected position." +msgstr "這裡已被保護,您不能在這裡建造鐵路。" + +#: advtrains/protection.lua:184 +msgid "" +"You are not allowed to operate turnouts and signals without the " +"railway_operator privilege." +msgstr "您沒有「railway_operator」許可權,不能控制鐵路設施。" + +#: advtrains_line_automation/stoprail.lua:54 +msgid "Station Code" +msgstr "車站碼" + +#: advtrains_line_automation/stoprail.lua:55 +msgid "Station Name" +msgstr "車站名稱" + +#: advtrains_line_automation/stoprail.lua:56 +msgid "Door Delay" +msgstr "車門關閉時間" + +#: advtrains_line_automation/stoprail.lua:57 +msgid "Dep. Speed" +msgstr "出發速度" + +#: advtrains_line_automation/stoprail.lua:58 advtrains_train_track/init.lua:11 +#: advtrains_train_track/init.lua:156 +msgid "Track" +msgstr "軌道" + +#: advtrains_line_automation/stoprail.lua:59 +msgid "Stop Time" +msgstr "停站時間" + +#: advtrains_line_automation/stoprail.lua:60 +msgid "Door Side" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:62 +msgid "Reverse train" +msgstr "" + +#: advtrains_line_automation/stoprail.lua:63 +msgid "Kick out passengers" +msgstr "" + +#: advtrains_luaautomation/pcnaming.lua:26 +msgid "" +"Passive Component Naming Tool\n" +"\n" +"Right-click to name a passive component." +msgstr "" +"被動元件命名工具\n" +"\n" +"右鍵單擊命名所選元件" + +#: advtrains_train_track/init.lua:31 +msgid "Y-turnout" +msgstr "對稱道岔" + +#: advtrains_train_track/init.lua:49 +msgid "3-way turnout" +msgstr "三開道岔" + +#: advtrains_train_track/init.lua:69 +msgid "Perpendicular Diamond Crossing Track" +msgstr "垂直交叉軌道" + +#: advtrains_train_track/init.lua:91 +msgid "90+Angle Diamond Crossing Track" +msgstr "交叉軌道 (其中一條軌道與座標軸平行)" + +#: advtrains_train_track/init.lua:132 +msgid "Diagonal Diamond Crossing Track" +msgstr "交叉軌道" + +#: advtrains_train_track/init.lua:179 +msgid "Bumper" +msgstr "保險槓" + +#: advtrains_train_track/init.lua:201 +msgid "ATC controller" +msgstr "ATC 控制器" + +#: advtrains_train_track/init.lua:317 +msgid "Unloading Track" +msgstr "卸貨軌道" + +#: advtrains_train_track/init.lua:342 +msgid "Loading Track" +msgstr "裝貨軌道" + +#: advtrains_train_track/init.lua:406 +msgid "Detector Rail" +msgstr "探測軌道" + +#: advtrains_train_industrial/init.lua:10 +#: advtrains_train_industrial/init.lua:49 advtrains_train_steam/init.lua:20 +#: advtrains_train_steam/init.lua:91 +msgid "Driver Stand (right)" +msgstr "右側司機座位" + +#: advtrains_train_industrial/init.lua:17 +#: advtrains_train_industrial/init.lua:56 advtrains_train_steam/init.lua:14 +#: advtrains_train_steam/init.lua:85 +msgid "Driver Stand (left)" +msgstr "左側司機座位" + +#: advtrains_train_industrial/init.lua:40 +msgid "Industrial Train Engine" +msgstr "工業用火車頭" + +#: advtrains_train_industrial/init.lua:79 +msgid "Big Industrial Train Engine" +msgstr "大型工業用火車頭" + +#: advtrains_train_industrial/init.lua:98 +msgid "Industrial tank wagon" +msgstr "液體運輸車廂" + +#: advtrains_train_industrial/init.lua:116 +msgid "Industrial wood wagon" +msgstr "木材運輸車廂" + +#: advtrains_train_japan/init.lua:4 +msgid "Japanese Train Inter-Wagon Connection" +msgstr "日本火車連結器" + +#: advtrains_train_japan/init.lua:37 +msgid "Driver stand" +msgstr "司機座位" + +#: advtrains_train_japan/init.lua:101 +msgid "Japanese Train Engine" +msgstr "高速列車車頭" + +#: advtrains_train_japan/init.lua:176 +msgid "Japanese Train Wagon" +msgstr "高速列車車廂" + +#: advtrains_train_steam/init.lua:75 +msgid "Steam Engine" +msgstr "蒸汽機車" + +#: advtrains_train_steam/init.lua:159 +msgid "Detailed Steam Engine" +msgstr "精細的蒸汽機車" + +#: advtrains_train_steam/init.lua:206 +msgid "Passenger Wagon" +msgstr "客車" + +#: advtrains_train_steam/init.lua:226 +msgid "Box Wagon" +msgstr "貨運車廂" + +#: advtrains_train_subway/init.lua:144 +msgid "Subway Passenger Wagon" +msgstr "地鐵車廂" + +#~ msgid "This position is protected!" +#~ msgstr "這裡已被保護。" + +#~ msgid "Can't place: protected position!" +#~ msgstr "無法放置:此區域已被保護。" + +#~ msgid "Deprecated Track" +#~ msgstr "請不要使用" + +#~ msgid "Can't get on: wagon full or doors closed!" +#~ msgstr "無法上車:車門已關閉或車廂已滿。" + +#~ msgid "Use Sneak+rightclick to bypass closed doors!" +#~ msgstr "請使用潛行+右鍵上車。" + +#~ msgid "Access to @1" +#~ msgstr "可前往@1" + +#~ msgid "" +#~ "ATC controller, mode @1\n" +#~ "Channel: @2" +#~ msgstr "" +#~ "ATC 控制器\n" +#~ "模式:@1\n" +#~ "頻道:@2" + +#~ msgid "Lock couples" +#~ msgstr "鎖定連結處" + +#~ msgid "" +#~ "You need to own at least one neighboring wagon to destroy this couple." +#~ msgstr "您必須至少擁有其中一節車廂才能分開這兩節車廂。" + +#~ msgid "Speed:" +#~ msgstr "速度" + +#~ msgid "Target:" +#~ msgstr "目標速度" + +#~ msgid "Default Seat" +#~ msgstr "預設座位" + +#~ msgid "Default Seat (driver stand)" +#~ msgstr "預設座位 (司機座位)" diff --git a/advtrains/protection.lua b/advtrains/protection.lua index 7474977..89e15eb 100644 --- a/advtrains/protection.lua +++ b/advtrains/protection.lua @@ -145,12 +145,12 @@ function advtrains.check_track_protection(pos, pname, near, prot_p) --atdebug("CTP: ",pos,pname,near,prot_p,"priv=",priv,"prot=",prot,"dprot=",dprot) if not priv and (not boo or prot or not dprot) then - minetest.chat_send_player(pname, "You are not allowed to build "..nears.."tracks without track_builder privilege") + minetest.chat_send_player(pname, near and attrans("You are not allowed to build near tracks without the track_builder privilege.") or attrans("You are not allowed to build tracks without the track_builder privilege.")) minetest.log("action", pname.." tried to modify terrain "..nears.."track at "..minetest.pos_to_string(apos).." but is not permitted to (no privilege)") return false end if prot then - minetest.chat_send_player(pname, "You are not allowed to build "..nears.."tracks at protected position!") + minetest.chat_send_player(pname, near and attrans("You are not allowed to build near tracks at this protected position.") or attrans("You are not allowed to build tracks at this protected position.")) minetest.record_protection_violation(pos, pname) minetest.log("action", pname.." tried to modify "..nears.."track at "..minetest.pos_to_string(apos).." but position is protected!") return false @@ -181,7 +181,7 @@ function advtrains.check_turnout_signal_protection(pos, pname) nocheck=false return true else - minetest.chat_send_player(pname, "You are not allowed to operate turnouts and signals (missing railway_operator privilege)") + minetest.chat_send_player(pname, attrans("You are not allowed to operate turnouts and signals without the railway_operator privilege.")) minetest.log("action", pname.." tried to operate turnout/signal at "..minetest.pos_to_string(pos).." but does not have railway_operator") nocheck=false return false diff --git a/advtrains/signals.lua b/advtrains/signals.lua index b26c950..74841d3 100644 --- a/advtrains/signals.lua +++ b/advtrains/signals.lua @@ -60,7 +60,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", tiles = {"advtrains_retrosignal.png"}, inventory_image="advtrains_retrosignal_inv.png", drop="advtrains:retrosignal_off", - description=attrans("Lampless Signal (@1)", attrans(r..rotation)), + description=attrans("Lampless Signal"), sunlight_propagates=true, groups = { cracky=3, @@ -124,7 +124,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", tiles = {"advtrains_signal_"..r..".png"}, inventory_image="advtrains_signal_inv.png", drop="advtrains:signal_off", - description=attrans("Signal (@1)", attrans(r..rotation)), + description=attrans("Signal"), groups = { cracky=3, not_blocking_trains=1, @@ -187,6 +187,11 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", if r=="off" then crea=0 end --tunnel signals. no rotations. + local swdesc = { -- needed for xgettext + l = attrans("Wallmounted Signal (l)"), + r = attrans("Wallmounted Signal (r)"), + t = attrans("Wallmounted Signal (t)"), + } for loc, sbox in pairs({l={-1/2, -1/2, -1/4, 0, 1/2, 1/4}, r={0, -1/2, -1/4, 1/2, 1/2, 1/4}, t={-1/2, 0, -1/4, 1/2, 1/2, 1/4}}) do minetest.register_node("advtrains:signal_wall_"..loc.."_"..r, { drawtype = "mesh", @@ -200,7 +205,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", mesh = "advtrains_signal_wall_"..loc..".b3d", tiles = {"advtrains_signal_wall_"..r..".png"}, drop="advtrains:signal_wall_"..loc.."_off", - description=attrans("Wallmounted Signal ("..loc..")"), + description=swdesc[loc], groups = { cracky=3, not_blocking_trains=1, @@ -314,7 +319,7 @@ minetest.register_node("advtrains:across_on", { mesh = "advtrains_across.obj", tiles = {{name="advtrains_across_anim.png", animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.0}}}, drop="advtrains:across_off", - description=attrans("Andrew's Cross (on) (you hacker you)"), + description=attrans("Andrew's Cross"), groups = { cracky=3, not_blocking_trains=1, -- cgit v1.2.3 From 425b0993d355b9f45ddd400bd4925f9f1a5bd34d Mon Sep 17 00:00:00 2001 From: "Y. Wang" Date: Wed, 4 Oct 2023 20:07:24 +0200 Subject: Autogenerate .tr files from .po files --- .build.yml | 6 + .gitignore | 3 +- advtrains/init.lua | 7 +- advtrains/locale/README.md | 70 +--- advtrains/locale/advtrains.de.tr | 159 --------- advtrains/locale/advtrains.fr.tr | 146 --------- advtrains/locale/advtrains.zh_CN.tr | 146 --------- advtrains/locale/advtrains.zh_TW.tr | 146 --------- advtrains/locale/gui | 638 ------------------------------------ advtrains/locale/template.txt | 146 --------- advtrains/locale/topo.sh | 4 - advtrains/po/README.md | 70 ++++ advtrains/poconvert.lua | 185 +++++++++++ advtrains/spec/poconvert_spec.lua | 70 ++++ 14 files changed, 338 insertions(+), 1458 deletions(-) mode change 100644 => 120000 advtrains/locale/README.md delete mode 100644 advtrains/locale/advtrains.de.tr delete mode 100644 advtrains/locale/advtrains.fr.tr delete mode 100644 advtrains/locale/advtrains.zh_CN.tr delete mode 100644 advtrains/locale/advtrains.zh_TW.tr delete mode 100755 advtrains/locale/gui delete mode 100644 advtrains/locale/template.txt delete mode 100755 advtrains/locale/topo.sh create mode 100644 advtrains/po/README.md create mode 100644 advtrains/poconvert.lua create mode 100644 advtrains/spec/poconvert_spec.lua (limited to 'advtrains/init.lua') diff --git a/.build.yml b/.build.yml index 135d1a5..c2332f2 100644 --- a/.build.yml +++ b/.build.yml @@ -6,6 +6,7 @@ packages: - unzip - wget - lua-busted +- luajit sources : - https://git.sr.ht/~gpcf/advtrains @@ -40,3 +41,8 @@ tasks: - run_test_world: | echo "bind_address = 127.0.0.1" > minetest.conf minetestserver --port 31111 --gameid minetest_game --config ~/minetest.conf --world ~/.minetest/worlds/advtrains_testworld --logfile ~/minetest.log +- test_po_files : | + cd advtrains/advtrains + for f in po/*.po; do + luajit -e 'require("poconvert").from_string("advtrains", io.input():read("*a"))' < $f + done diff --git a/.gitignore b/.gitignore index 2920966..ed106ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ ## Eclipse project files & directories .project .settings -*~ +advtrains/locale/*.tr +advtrains/po/*~ diff --git a/advtrains/init.lua b/advtrains/init.lua index f6f8f9b..cb2214d 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -22,8 +22,6 @@ Copyright (C) 2016-2020 Moritz Blei (orwell96) and contributors local lot = os.clock() minetest.log("action", "[advtrains] Loading...") -attrans = minetest.get_translator("advtrains") - --advtrains advtrains = {trains={}, player_to_train_mapping={}} @@ -200,6 +198,10 @@ advtrains.meseconrules = advtrains.fpath=minetest.get_worldpath().."/advtrains" +advtrains.poconvert = dofile(advtrains.modpath.."/poconvert.lua") +advtrains.poconvert.from_flat("advtrains") +attrans = minetest.get_translator("advtrains") + advtrains.speed = dofile(advtrains.modpath.."/speed.lua") advtrains.texture = dofile(advtrains.modpath.."/texture.lua") @@ -233,7 +235,6 @@ end dofile(advtrains.modpath.."/lzb.lua") - --load/save -- backup variables, used if someone should accidentally delete a sub-mod diff --git a/advtrains/locale/README.md b/advtrains/locale/README.md deleted file mode 100644 index a54cb6c..0000000 --- a/advtrains/locale/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Translations -**Please note that this document is outdated as transition to `.po` -files is currently in progress.** - -Please read this document before working on any translations. - -## Getting Started -If there is a translation file for your language (e.g. German), you can -edit the file directly. Please read [the documentation on the -translation file format][tr-format]. - -Alternatively, Advtrains provides a script named `gui` that can be used -to, among other things, edit translation files. The script requires -Tcl/Tk 8.6, which is provided by most Linux distributions. - -If the translation file for your language does not exist, create it by -copying `template.txt` to `advtrains.XX.tr`, where `XX` is replaced by -the language code. - -Feel free to use the [discussion mailing list][srht-discuss] if you -have any questions regarding localization. - -You can share your `.tr` file directly or [as a patch][gsm] to the [dev -mailing list][srht-devel]. The latter is encouraged, but, unlike code -changes, translation files sent directly are also accepted. - -[tr-format]: https://minetest.gitlab.io/minetest/translations/#translation-file-format -[srht-discuss]: https://lists.sr.ht/~gpcf/advtrains-discuss -[srht-devel]: https://lists.sr.ht/~gpcf/advtrains-devel -[gsm]: https://git-send-email.io - -## Translation Notes -* Translations should be consistent. You can use other entries or the -translations in Minetest as a reference. -* Translations do not have to fully correspond to the original text - -they only need to provide the same information. In particular, -translations do not need to have the same linguistical structure as the -original text. -* Replacement sequences (`@1`, `@2`, etc) should not be translated. -* Certain abbreviations or names, such as "Ks" or "Zs 3", should -generally not be translated. - -### (de) German -* Verwenden Sie die neue Rechtschreibung und die Sie-Form. -* Mit der deutschen Tastaturbelegung unter Linux können die -Anführungszeichen „“ mit AltGr-V bzw. AltGr-B eingegeben werden. - -### (zh) Chinese -(This section is written in English to avoid writing the note twice or -using only one of the variants, as most of this section applies to both -the traditional and simplified variants.) - -* Please use the 「」 quotation marks for Traditional Chinese and “” -for Simplified Chinese. -* Please use the fullwidth variants of: , 、 。 ? ! : ; -* Please use the halfwidth variants of: ( ) [ ] / \ | -* Please do not leave any space between Han characters (including -fullwidth punctuation marks). -* Please leave a space between Han characters (excluding fullwidth -punctuation marks) and characters from other scripts (including -halfwidth punctuation marks). However, do not leave any space between -Han characters and Arabic numerals. - -## Notes for developers -* Avoid word-by-word translations. -* Avoid manipulating translated strings (except for concatenation). Use -server-side translations if you have to modify the text sent to users. -* Avoid truncating strings unless multibyte characters are handled -properly. diff --git a/advtrains/locale/README.md b/advtrains/locale/README.md new file mode 120000 index 0000000..61e473c --- /dev/null +++ b/advtrains/locale/README.md @@ -0,0 +1 @@ +../po/README.md \ No newline at end of file diff --git a/advtrains/locale/advtrains.de.tr b/advtrains/locale/advtrains.de.tr deleted file mode 100644 index 1065264..0000000 --- a/advtrains/locale/advtrains.de.tr +++ /dev/null @@ -1,159 +0,0 @@ -# textdomain: advtrains - -# Advtrains Core (unorganized) -This wagon is owned by @1, you can't destroy it.=Dieser Waggon gehört @1, Sie dürfen ihn nicht abbauen. -Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Warnung: Durch den Abbau des Waggons erhalten Sie nur etwas Stahl zurück. Nutzen Sie Schleichen+Linksklick, um dem Waggon abzubauen. -This position is protected!=Diese Position ist geschützt! -Can't place: not pointing at node=Es kann nicht platziert werden: Sie zeigen nicht auf einem Block. -Can't place: space occupied!=Es kann nicht platziert werden: diese Position ist besetzt. -Can't place: protected position!=Es kann nicht platziert werden: diese Position ist geschützt. -Can't place: Not enough slope items left (@1 required)=Es kann nicht platziert werden: Sie haben nicht genug Steigungsblöcke, es werden insgesamt @1 benötigt. -Can't place: There's no slope of length @1=Es kann nicht platziert werden: die Steigung der Länge @1 ist nicht definiert. -Can't place: no supporting node at upper end.=Es kann nicht platziert werden: es gibt keinen unterstützenden Block am Ende der Steigung. -Deprecated Track=ausrangiertes Gleis, nicht verwenden. -Can't get on: wagon full or doors closed!=Sie können nicht einsteigen: der Waggon ist voll oder die Türen sind geschlossen. -Use Sneak+rightclick to bypass closed doors!=Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen einzusteigen. -Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Die Türen sind geschlossen. Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen auszusteigen. -Access to @1=Zugang zu @1 -You do not have the @1 privilege.=Ihnen fehlt das „@1“-Privileg. -The wagon's inventory is not empty!=Das Inventar dieses Waggons ist nicht leer! -Position is occupied by a train.=Ein Zug steht an dieser Position. -There's a Track Circuit Break here.=Hier ist eine Gleisabschnittsgrenze (TCB). -There's a Signal Influence Point here.=Hier ist ein Signal-Beeinflussungspunkt. - -# Trackworker, rotation, adjustment -This node can't be rotated using the trackworker!=Dieser Block kann nicht mit dem Gleiswerkzeug gedreht werden. -This node can't be changed using the trackworker!=Dieser Block kann nicht mit dem Gleiswerkzeug bearbeitet werden. -This track can not be changed!=Dieses Gleis kann nicht geändert werden! -This track can not be rotated!=Dieses Gleis kann nicht gedreht werden! -This track can not be removed!=Dieses Gleis kann nicht entfernt werden! - -# ATC -ATC controller, unconfigured.=Nicht konfiguierte Zugbeeinflussungsgleis -ATC controller=Zugbeeinflussungsgleis -ATC controller, mode @1@nChannel: @2=Zugbeeinflussungsgleis in Betriebsart „@1“@nKanal: @2 -ATC controller, mode @1@nCommand: @2=Zugbeeinflussungsgleis in Betriebsart „@1“@nBefehl: @2 -Command=Befehl -Command (on)=Befehl (wenn aktiviert) -Digiline channel=Digiline-Kanal -ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed -ATC Kick command warning: Train moving=ATC Kick command warning: Train moving -ATC Reverse command warning: didn't reverse train, train moving!=Zugbeeinflussung: der Befehl „R“ wurde nicht ausgeführt, Zug in Bewegung! -ATC command syntax error: I statement not closed: @1=Zugbeeinflussung: Unvollständiger I-Befehl: @1 -ATC command parse error: Unknown command: @1=Zugbeeinflussung: Unbekannter Befehl: @1 - -# Coupling -Lock couples=Kupplungen sperren -You need to own at least one neighboring wagon to destroy this couple.=Sie müssen Besitzer eines angrenzenden Waggons sein, um hier abzukuppeln. -Buffer and Chain Coupler=Schraubenkupplung -Scharfenberg Coupler=Scharfenbergkupplung -Japanese Train Inter-Wagon Connection=Waggonzwischenverbindung Japanischer Personenzüge -Can not couple: The couplers of the trains do not match (@1 and @2).=Die Kupplungen der Züge passen nicht zueinander (@1 und @2). -You are not allowed to couple trains without the train_operator privilege.=Sie dürfen ohne das „train_builder“-Privileg keine Züge ankuppeln. - -# Clipboard -The track you are trying to place the wagon on is not long enough!=Das Gleis, auf dem der Waggon platziert werden woll, ist zu kurz. -The clipboard couldn't access the metadata. Paste failed.=Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte eine Kopie des Zuges nicht eingefügt werden. -The clipboard couldn't access the metadata. Copy failed.=Wegen des fehlgeschlagenen Zugriffs auf die Metadaten konnte der Zug nicht kopiert werden. -The clipboard is empty.=Das Clipboard ist leer. -Back of train would end up off track, cancelling.=Der hinterer Teil dez Zuges wäre nicht auf dem Gleis. -No such lua entity!=Sie zeigen nicht auf einem Objekt, das mit diesem Werkzeug kopiert werden kann. -No such wagon: @1=Es gibt keinen mit „@1“ identifizierbaren Waggon. -No such train: @1=Es gibt keinen mit „@1“ identifizierbaren Zug. -Train copied!=Der Zug wurde Kopiert. - -# Protection -You are not allowed to build tracks without the track_builder privilege.=Sie dürfen ohne das „track_builder“-Privileg kein Gleis bauen. -You are not allowed to build near tracks without the track_builder privilege.=Sie dürfen ohne das „track_builder“-Privileg nicht in der Nähe von Gleisen bauen. -You are not allowed to build tracks at this protected position.=Sie dürfen an geschützten Stellen kein Gleis bauen. -You are not allowed to build near tracks at this protected position.=Sie dürfen an geschützten Stellen nicht in der Nähe von Gleisen bauen. -You are not allowed to operate turnouts and signals without the railway_operator privilege.=Sie dürfen ohne das „railway_operator“-Privileg keine Bahnanlage operieren. - -# Train HUD/Formspecs -Speed:=Geschw.: -Target:=Zielges.: -Show Inventory=Inventar Zeigen -Select seat:=Wählen Sie einen Sitzplatz aus: -Wagon properties=Waggon-Einstellungen -Save wagon properties=Waggon-Einstellungen speichern -Text displayed outside on train=Äußere Anzeige -Text displayed inside train=Innere Anzeige -Line=Linie -Routingcode=Routingcode -Get off=Aussteigen -Get off (forced)=Ausstieg zwingen -(Doors closed)=(Türen geschlossen) - -# General -Save=Speichern - -# Line automation -Station Code=Code der Haltestelle -Station Name=Name der Haltestelle -Door Delay=Zeit für die Türschließung -Door Side=Door Side -Dep. Speed=Zielgeschwindigkeit bei Abfahrt -Stop Time=Wartezeit - -# Items -Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Gleiswerkzeug@n@nLinksklick: Gleistyp ändern, Rechtsklick: Objekt drehen. -Passive Component Naming Tool@n@nRight-click to name a passive component.=PC-Benennungswerkzeug@n@nRechtsklick zur Benennung der passiven Komponente -Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Werkzeug zur Erstellung von Zugkopien@n@nLinksklick: Zug ins Clipboard kopieren@nRight-click: Kopierten Zug einfügen -Track=Gleis -Perpendicular Diamond Crossing Track=Kreuzung mit zueinander orthogonalen Gleisen -Diagonal Diamond Crossing Track=Diagonale Gleiskreuzung -90+Angle Diamond Crossing Track=Kreuzung mit einem achsenparallelen Gleis -Y-turnout=Y-Weiche -3-way turnout=Dreiwegweiche -Unloading Track=Abladungsgleis -Loading Track=Beladungsgleis -Bumper=Prellbock -Detector Rail=Detektorgleis -@1 Slope=@1 Steigung -@1 Platform (low)=Niedriger @1-Bahnsteig -@1 Platform (high)=Hoher @1-Bahnsteig -@1 Platform (low, 45 degree)=Niedriger @1-Bahnsteig (45°) -@1 Platform (45 degree)=Hoher @1-Bahnsteig (45°) -Lampless Signal=Mechanisches Signal -Signal=Lichtsignal -Wallmounted Signal (l)=An der linken Seite montiertes Signal -Wallmounted Signal (r)=An der rechten Seite montiertes Signal -Wallmounted Signal (t)=An der Decke montiertes Signal -Andrew's Cross=Andrew's Cross -Boiler=Boiler -driver's cab=driver's cab -Wheel=Wheel -Chimney=Chimney - -# Seats -Default Seat=Standardsitzplatz -Default Seat (driver stand)=Standardsitzplatz (Führerstand) -Driver stand=Führerstand -Driver Stand (left)=Führerstand Links -Driver Stand (right)=Führerstand Rechts - -# Wagon/engine types -Industrial Train Engine=Industrielle Lokomotive -Big Industrial Train Engine=Große Industrielle Lokomotive -Industrial tank wagon=Tankwaggon -Industrial wood wagon=Holztransportwaggon -Japanese Train Engine=Japanische Personenzug-Lokomotive -Japanese Train Wagon=Japanischer Personenzug-Passagierwaggon -Steam Engine=Dampflokomotive -Detailed Steam Engine=detaillierte Dampflokomotive -Passenger Wagon=Passagierwaggon -Box Wagon=Güterwaggon -Subway Passenger Wagon=U-Bahn-Waggon -The wagon's inventory is not empty!=Das Inventar dieses Waggons ist nicht leer! -This track can not be changed!=Diese Schiene kann nicht geändert werden! -This track can not be rotated!=Diese Schiene kann nicht gedreht werden! -This track can not be removed!=Diese Schiene kann nicht entfernt werden! -Position is occupied by a train.=Ein Zug steht an dieser Position. -There's a Track Circuit Break here.=Hier ist eine Gleisabschnittsgrenze (TCB). -There's a Signal Influence Point here.=Hier ist ein Signal-Beeinflussungspunkt. -Buffer and Chain Coupler=Schraubenkupplung -Scharfenberg Coupler=Scharfenbergkupplung -Japanese Train Inter-Wagon Connection=Waggonzwischenverbindung Japanischer Personenzug -Can not couple: The couplers of the trains do not match (@1 and @2).=Kann nicht ankuppeln: Die Kupplungen der Züge passen nicht zueinander (@1 und @2) -Train ID=Zugnummer -= diff --git a/advtrains/locale/advtrains.fr.tr b/advtrains/locale/advtrains.fr.tr deleted file mode 100644 index 0dd6d00..0000000 --- a/advtrains/locale/advtrains.fr.tr +++ /dev/null @@ -1,146 +0,0 @@ -# textdomain: advtrains - -# Advtrains Core (unorganized) -This wagon is owned by @1, you can't destroy it.=Ce wagon est la propriété de @1, vous ne pouvez pas le détruire. -Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Attention: Si vous détruisez ce wagon, vous ne récupérerez que de la ferraille ! Si vous êtes sûr de vous, appuyez la touche "Marcher lentement (Sneak)" et Clic-Gauche. -This position is protected!=Cet emplacement est protégé ! -Can't place: not pointing at node=Placement impossible : ne pointe pas un nœud -Can't place: space occupied!=Placement impossible : espace occupé -Can't place: protected position!=Placement impossible : emplacement protégé -Can't place: Not enough slope items left (@1 required)=Placement impossible : quantité insuffisante de voie pentue (@1 manquant) -Can't place: There's no slope of length @1=Placement impossible : il n'y a pas de voie pentue de longueur @1 -Can't place: no supporting node at upper end.=Placement impossible : pas de nœud d'appui à l'extrémité supérieure -Deprecated Track=Voie déconseillée -Can't get on: wagon full or doors closed!=Embarquement impossible : le wagon est plein ou ses portes sont closes ! -Use Sneak+rightclick to bypass closed doors!=Utilisez "Marcher lentement (Sneak)" et Clic-Droit pour franchir les portes closes ! -Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Portes closes ! Utilisez "Marcher lentement (Sneak)" et Clic-Droit pour franchir les portes et débarquer ! -Access to @1=Accès à @1 -You do not have the @1 privilege.=Vous ne possédez pas le privilège "@1". -The wagon's inventory is not empty!=Le stock de ce wagon n'est pas vide ! -Position is occupied by a train.=Cet emplacement est occupé par un train. -There's a Track Circuit Break here.=Il y a un "Track Circuit Break" ici. -There's a Signal Influence Point here.=Il y a un "Signal Influence Point" ici. - -# Trackworker, rotation, adjustment -This node can't be rotated using the trackworker!=Ce nœud ne peut être tourné avec l'outil "Trackworker" ! -This node can't be changed using the trackworker!=Ce nœud ne peut être modifié avec l'outil "Trackworker" ! -This track can not be changed!=Cette voie ne peut pas être modifiée ! -This track can not be rotated!=Cette voie ne peut pas être tournée ! -This track can not be removed!=Cette voie ne peut pas être enlevée ! - -# ATC -ATC controller, unconfigured.=Controlleur ATC, non-configuré -ATC controller=Controlleur ATC -ATC controller, mode @1@nChannel: @2=Controlleur ATC, mode @1@nCanal : @2 -ATC controller, mode @1@nCommand: @2=Controlleur ATC, mode @1@nCommande : @2 -Command=Commande -Command (on)=Commande (marche) -Digiline channel=Canal Digiline -ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed -ATC Kick command warning: Train moving=ATC Kick command warning: Train moving -ATC Reverse command warning: didn't reverse train, train moving!=Attention : Commande ATC de renversement impossible car le train se déplace ! -ATC command syntax error: I statement not closed: @1=Erreur de syntaxe de commande ATC : instruction "I" incomplète : @1 -ATC command parse error: Unknown command: @1=Erreur d'analyse de commande ATC : Commande inconnue : @1 - -# Coupling -Lock couples=Verrouiller l'accouplement -You need to own at least one neighboring wagon to destroy this couple.=Vous devez être propriétaire d'au moins un wagon voisin pour supprimer cet attelage. -Buffer and Chain Coupler=Attelage à tampon et vis -Scharfenberg Coupler=Attelage Scharfenberg -Japanese Train Inter-Wagon Connection=Passage inter-voiture de train Japonais -Can not couple: The couplers of the trains do not match (@1 and @2).=Accouplement impossible: les attelages des trains ne concordent pas (@1 et @2). -You are not allowed to couple trains without the train_operator privilege.=You are not allowed to couple trains without the train_operator privilege. - -# Clipboard -The track you are trying to place the wagon on is not long enough!=La voie sur laquelle vous tentez de placer le wagon est trop courte ! -The clipboard couldn't access the metadata. Paste failed.=Le presse-papier ne peut accéder aux métadonnées. Échec du collage. -The clipboard couldn't access the metadata. Copy failed.=Le presse-papier ne peut accéder aux métadonnées. Échec de la copie. -The clipboard is empty.=Le presse-papier est vide. -Back of train would end up off track, cancelling.=La fin du train serait hors voie : annulation. -No such lua entity!=Pas de telle entité lua ! -No such wagon: @1=Pas de tel wagon : @1 -No such train: @1=Pas de tel train : @1 -Train copied!=Train copié ! - -# Protection -You are not allowed to build tracks without the track_builder privilege.=Vous ne pouvez pas construire une voie sans le privilège "track_builder" -You are not allowed to build near tracks without the track_builder privilege.=Vous ne pouvez pas construire à proximité d'une voie sans le privilège "track_builder" (?) -You are not allowed to build tracks at this protected position.=Vous ne pouvez pas construire une voie à cet emplacement protégé -You are not allowed to build near tracks at this protected position.=Vous ne pouvez pas construire à proximité d'une voie à cet emplacement protégé -You are not allowed to operate turnouts and signals without the railway_operator privilege.=Vous ne pouvez pas actionner les aiguillages ou les signaux (privilège "railway_operator" manquant) - -# Train HUD/Formspecs -Speed:=Vitesse : -Target:=Destination : -Show Inventory=Montrer le stock -Select seat:=Choisir le siège -Wagon properties=Propriétés du wagon -Save wagon properties=Sauvegarder les propriétés du wagon -Text displayed outside on train=Texte affiché à l'extérieur du train -Text displayed inside train=Texte affiché à l'intérieur du train -Line=Ligne -Routingcode=Code de routage -Get off=Débarquer -Get off (forced)=Débarquer (de force) -(Doors closed)=(Portes closes) - -# General -Save=Sauvegarder - -# Line automation -Station Code=Code de Station -Station Name=Nom de Station -Door Delay=Durée d'ouverture des portes -Door Side=Door Side -Dep. Speed=Vitesse de départ -Stop Time=Durée d'arrêt - -# Items -Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Outil "Trackworker"@n@nClic-Gauche : change le type de rail (droit/courbé/aiguillage)@n@nClic-Droit : tourne le rail/butoir/signal/etc... -Passive Component Naming Tool@n@nRight-click to name a passive component.=Outil de nommage de composant passif@n@nClic-Droit pour nommer un composant passif. -Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Outil de copie/collage de train@n@nClic-Gauche : copie@n@nClic-Droit : collage -Track=Voie -Perpendicular Diamond Crossing Track=Croisement perpendiculaire -Diagonal Diamond Crossing Track=Croisement diagonal -90+Angle Diamond Crossing Track=Croisement perpendiculo-diagonal -Y-turnout=Embranchement en Y -3-way turnout=Embranchement triple -Unloading Track=Voie de Déchargement -Loading Track=Voie de Chargement -Bumper=Heurtoir -Detector Rail=Voie détectrice -@1 Slope=Pente @1 -@1 Platform (low)=Quai @1 (bas) -@1 Platform (high)=Quai @1 (haut) -@1 Platform (low, 45 degree)=Quai @1 (bas, 45°) -@1 Platform (45 degree)=Quai @1 (haut, 45°) -Lampless Signal=Sémaphore -Signal=Signal -Wallmounted Signal (l)=Signal mural (gauche) -Wallmounted Signal (r)=Signal mural (droit) -Wallmounted Signal (t)=Signal mural (plafond) -Andrew's Cross=Croix de Saint André -Boiler=Chaudière à vapeur -driver's cab=Cabine de pilotage -Wheel=Roue -Chimney=Cheminée - -# Seats -Default Seat=Siège par défaut -Default Seat (driver stand)=Siège par défaut (poste de pilotage) -Driver stand=Poste de pilotage -Driver Stand (left)=Poste de pilotage (gauche) -Driver Stand (right)=Poste de pilotage (droit) - -# Wagon/engine types -Industrial Train Engine=Locomotive industrielle -Big Industrial Train Engine=Grosse locomotive industrielle -Industrial tank wagon=Wagon-citerne industriel -Industrial wood wagon=Wagon grumier industriel -Japanese Train Engine=Motrice Japonaise -Japanese Train Wagon=Voiture Japonaise -Steam Engine=Locomotive à vapeur -Detailed Steam Engine=Locomotive à vapeur complexe -Passenger Wagon=Voiture passager -Box Wagon=Wagon de frêt -Subway Passenger Wagon=Voiture de Métropolitain diff --git a/advtrains/locale/advtrains.zh_CN.tr b/advtrains/locale/advtrains.zh_CN.tr deleted file mode 100644 index 6ed4887..0000000 --- a/advtrains/locale/advtrains.zh_CN.tr +++ /dev/null @@ -1,146 +0,0 @@ -# textdomain: advtrains - -# Advtrains Core (unorganized) -This wagon is owned by @1, you can't destroy it.=这是 @1 的车厢,您不能摧毁它。 -Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=警告:如果您摧毁此车厢,您只能拿到一些钢方块。如果您确定要摧毁这节车厢,请按潜行键并左键单击此车厢。 -This position is protected!=这里已被保护。 -Can't place: not pointing at node=无法放置:您没有选择任何方块。 -Can't place: space occupied!=无法放置:此区域已被占用。 -Can't place: protected position!=无法放置:此区域已被保护。 -Can't place: Not enough slope items left (@1 required)=无法放置:您没有足够的铁路斜坡放置工具 (您总共需要@1个) -Can't place: There's no slope of length @1=无法放置:advtrains 不支持长度为@1米的斜坡。 -Can't place: no supporting node at upper end.=无法放置:较高端没有支撑方块。 -Deprecated Track=请不要使用 -Can't get on: wagon full or doors closed!=无法上车:车门已关闭或车厢已满。 -Use Sneak+rightclick to bypass closed doors!=请使用潜行+右键上车。 -Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=车门已关闭,请使用潜行+右键单击下车。 -Access to @1=可前往@1 -You do not have the @1 privilege.=您没有“@1”权限。 -The wagon's inventory is not empty!=The wagon's inventory is not empty! -Position is occupied by a train.=Position is occupied by a train. -There's a Track Circuit Break here.=There's a Track Circuit Break here. -There's a Signal Influence Point here.=There's a Signal Influence Point here. - -# Trackworker, rotation, adjustment -This node can't be rotated using the trackworker!=您不能使用铁路调整工具旋转这个方块。 -This node can't be changed using the trackworker!=您不能使用铁路调整工具调整这个方块。 -This track can not be changed!=您不能调整这段轨道。 -This track can not be rotated!=您不能旋转这段轨道。 -This track can not be removed!=您不能移除这段轨道。 - -# ATC -ATC controller, unconfigured.=ATC 控制器 (未配置) -ATC controller=ATC 控制器 -ATC controller, mode @1@nChannel: @2=ATC 控制器@n模式:@1@n频道:@2 -ATC controller, mode @1@nCommand: @2=ATC 控制器@n模式:@1@n命令:@2 -Command=命令 -Command (on)=命令 (激活时) -Digiline channel=Digiline 频道 -ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed -ATC Kick command warning: Train moving=ATC Kick command warning: Train moving -ATC Reverse command warning: didn't reverse train, train moving!=ATC 警告:未执行“R”命令,火车在移动 -ATC command syntax error: I statement not closed: @1=ATC 语法错误:“I”命令不完整:@1 -ATC command parse error: Unknown command: @1=ATC 语法错误:未知命令:@1 - -# Coupling -Lock couples=锁定连接处 -You need to own at least one neighboring wagon to destroy this couple.=您必须至少拥有其中一节车厢才能分开这两节车厢。 -Buffer and Chain Coupler=链式车钩 -Scharfenberg Coupler=Scharfenberg 式车钩 -Japanese Train Inter-Wagon Connection=日本火车车钩 -Can not couple: The couplers of the trains do not match (@1 and @2).=您无法连接这两节车厢:这两节车厢使用不同的车钩 (@1和@2)。 -You are not allowed to couple trains without the train_operator privilege.=您没有“train_operator”权限,不能连接这两节车厢。 - -# Clipboard -The track you are trying to place the wagon on is not long enough!=轨道太短。 -The clipboard couldn't access the metadata. Paste failed.=无法粘贴:剪贴板无法访问元数据。 -The clipboard couldn't access the metadata. Copy failed.=无法复制:剪贴板无法访问元数据。 -The clipboard is empty.=剪贴板是空的。 -Back of train would end up off track, cancelling.=火车后部不在轨道上。 -No such lua entity!=您没有指向一个可以用火车复制工具复制的物体。 -No such wagon: @1=ID 为“@1”的车厢不存在。 -No such train: @1=ID 为“@1”的列车不存在。 -Train copied!=已复制 - -# Protection -You are not allowed to build tracks without the track_builder privilege.=您没有“train_operator”权限,不能在这里建造铁路。 -You are not allowed to build near tracks without the track_builder privilege.=您没有“train_operator”权限,不能在铁路附近建任何东西。 -You are not allowed to build tracks at this protected position.=这里已被保护,您不能在这里建造铁路。 -You are not allowed to build near tracks at this protected position.=这里已被保护,您不能在这里的铁路附近建任何东西。 -You are not allowed to operate turnouts and signals without the railway_operator privilege.=您没有“railway_operator”权限,不能控制铁路设施。 - -# Train HUD/Formspecs -Speed:=速度 -Target:=目标速度 -Show Inventory=显示物品栏 -Select seat:=请选择座位 -Wagon properties=车厢属性 -Save wagon properties=保存车厢属性 -Text displayed outside on train=车厢外部显示 -Text displayed inside train=车厢内部显示 -Line=火车线路 -Routingcode=路由码 -Get off=下车 -Get off (forced)=强制下车 -(Doors closed)=(车门已关闭) - -# General -Save=保存 - -# Line automation -Station Code=车站代码 -Station Name=车站名称 -Door Delay=车门关闭时间 -Door Side=Door Side -Dep. Speed=出发速度 -Stop Time=停站时间 - -# Items -Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=铁路调整工具@n@n左键单击:切换轨道类型@n右键单击:旋转方块 -Passive Component Naming Tool@n@nRight-click to name a passive component.=被动元件命名工具@n@n右键单击命名所选元件 -Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=火车复制工具@n@n左键单击:复制@n右键单击:粘帖 -Track=轨道 -Perpendicular Diamond Crossing Track=垂直交叉轨道 -Diagonal Diamond Crossing Track=交叉轨道 -90+Angle Diamond Crossing Track=交叉轨道 (其中一条轨道与坐标轴平行) -Y-turnout=对称道岔 -3-way turnout=三开道岔 -Unloading Track=卸货轨道 -Loading Track=装货轨道 -Bumper=保险杠 -Detector Rail=探测轨道 -@1 Slope=@1斜坡 -@1 Platform (low)=较低的@1站台 -@1 Platform (high)=较高的@1站台 -@1 Platform (low, 45 degree)=较低的@1站台 (45°) -@1 Platform (45 degree)=较高的@1站台 (45°) -Lampless Signal=臂板信号机 -Signal=信号灯 -Wallmounted Signal (l)=壁挂式信号灯 (左侧) -Wallmounted Signal (r)=壁挂式信号灯 (右侧) -Wallmounted Signal (t)=悬挂式信号灯 -Andrew's Cross=铁路道口信号灯 -Boiler=锅炉 -driver's cab=驾驶室 -Wheel=车轮 -Chimney=烟囱 - -# Seats -Default Seat=默认座位 -Default Seat (driver stand)=默认座位 (司机座位) -Driver stand=司机座位 -Driver Stand (left)=左侧司机座位 -Driver Stand (right)=右侧司机座位 - -# Wagon/engine types -Industrial Train Engine=工业用火车头 -Big Industrial Train Engine=大型工业用火车头 -Industrial tank wagon=液体运输车厢 -Industrial wood wagon=木材运输车厢 -Japanese Train Engine=高速列车车头 -Japanese Train Wagon=高速列车车厢 -Steam Engine=蒸汽机车 -Detailed Steam Engine=精细的蒸汽机车 -Passenger Wagon=客车 -Box Wagon=货运车厢 -Subway Passenger Wagon=地铁车厢 diff --git a/advtrains/locale/advtrains.zh_TW.tr b/advtrains/locale/advtrains.zh_TW.tr deleted file mode 100644 index 37cce79..0000000 --- a/advtrains/locale/advtrains.zh_TW.tr +++ /dev/null @@ -1,146 +0,0 @@ -# textdomain: advtrains - -# Advtrains Core (unorganized) -This wagon is owned by @1, you can't destroy it.=這是 @1 的車廂,您不能摧毀它。 -Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=警告:如果您摧毀此車廂,您只能拿到一些鋼方塊。如果您確定要摧毀這節車廂,請按潛行鍵並左鍵單擊此車廂。 -This position is protected!=這裡已被保護。 -Can't place: not pointing at node=無法放置:您沒有選擇任何方塊。 -Can't place: space occupied!=無法放置:此區域已被佔用。 -Can't place: protected position!=無法放置:此區域已被保護。 -Can't place: Not enough slope items left (@1 required)=無法放置:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個) -Can't place: There's no slope of length @1=無法放置:advtrains 不支援長度為@1米的斜坡。 -Can't place: no supporting node at upper end.=無法放置:較高階沒有支撐方塊。 -Deprecated Track=請不要使用 -Can't get on: wagon full or doors closed!=無法上車:車門已關閉或車廂已滿。 -Use Sneak+rightclick to bypass closed doors!=請使用潛行+右鍵上車。 -Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=車門已關閉,請使用潛行+右鍵單擊下車。 -Access to @1=可前往@1 -You do not have the @1 privilege.=您沒有「@1」許可權。 -The wagon's inventory is not empty!=The wagon's inventory is not empty! -Position is occupied by a train.=Position is occupied by a train. -There's a Track Circuit Break here.=There's a Track Circuit Break here. -There's a Signal Influence Point here.=There's a Signal Influence Point here. - -# Trackworker, rotation, adjustment -This node can't be rotated using the trackworker!=您不能使用鐵路調整工具旋轉這個方塊。 -This node can't be changed using the trackworker!=您不能使用鐵路調整工具調整這個方塊。 -This track can not be changed!=您不能調整這段軌道。 -This track can not be rotated!=您不能旋轉這段軌道。 -This track can not be removed!=您不能移除這段軌道。 - -# ATC -ATC controller, unconfigured.=ATC 控制器 (未配置) -ATC controller=ATC 控制器 -ATC controller, mode @1@nChannel: @2=ATC 控制器@n模式:@1@n頻道:@2 -ATC controller, mode @1@nCommand: @2=ATC 控制器@n模式:@1@n命令:@2 -Command=命令 -Command (on)=命令 (啟用時) -Digiline channel=Digiline 頻道 -ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed -ATC Kick command warning: Train moving=ATC Kick command warning: Train moving -ATC Reverse command warning: didn't reverse train, train moving!=ATC 警告:未執行「R」命令,火車在移動 -ATC command syntax error: I statement not closed: @1=ATC 語法錯誤:「I」命令不完整:@1 -ATC command parse error: Unknown command: @1=ATC 語法錯誤:未知命令:@1 - -# Coupling -Lock couples=鎖定連結處 -You need to own at least one neighboring wagon to destroy this couple.=您必須至少擁有其中一節車廂才能分開這兩節車廂。 -Buffer and Chain Coupler=鏈式連結器 -Scharfenberg Coupler=Scharfenberg 式連結器 -Japanese Train Inter-Wagon Connection=日本火車連結器 -Can not couple: The couplers of the trains do not match (@1 and @2).=您無法連結這兩節車廂:這兩節車廂使用不同的連結器 (@1和@2)。 -You are not allowed to couple trains without the train_operator privilege.=您沒有「train_operator」許可權,不能連結這兩節車廂。 - -# Clipboard -The track you are trying to place the wagon on is not long enough!=軌道太短。 -The clipboard couldn't access the metadata. Paste failed.=無法貼上:剪貼簿無法訪問元資料。 -The clipboard couldn't access the metadata. Copy failed.=無法複製:剪貼簿無法訪問元資料。 -The clipboard is empty.=剪貼簿是空的。 -Back of train would end up off track, cancelling.=火車後部不在軌道上。 -No such lua entity!=您沒有指向一個可以用火車複製工具複製的物體。 -No such wagon: @1=ID 為「@1」的車廂不存在。 -No such train: @1=ID 為「@1」的列車不存在。 -Train copied!=已複製 - -# Protection -You are not allowed to build tracks without the track_builder privilege.=您沒有「train_operator」許可權,不能在這裡建造鐵路。 -You are not allowed to build near tracks without the track_builder privilege.=您沒有「train_operator」許可權,不能在鐵路附近建任何東西。 -You are not allowed to build tracks at this protected position.=這裡已被保護,您不能在這裡建造鐵路。 -You are not allowed to build near tracks at this protected position.=這裡已被保護,您不能在這裡的鐵路附近建任何東西。 -You are not allowed to operate turnouts and signals without the railway_operator privilege.=您沒有「railway_operator」許可權,不能控制鐵路設施。 - -# Train HUD/Formspecs -Speed:=速度 -Target:=目標速度 -Show Inventory=顯示物品欄 -Select seat:=請選擇座位 -Wagon properties=車廂屬性 -Save wagon properties=儲存車廂屬性 -Text displayed outside on train=車廂外部顯示 -Text displayed inside train=車廂內部顯示 -Line=火車線路 -Routingcode=路由碼 -Get off=下車 -Get off (forced)=強制下車 -(Doors closed)=(車門已關閉) - -# General -Save=儲存 - -# Line automation -Station Code=車站碼 -Station Name=車站名稱 -Door Delay=車門關閉時間 -Door Side=Door Side -Dep. Speed=出發速度 -Stop Time=停站時間 - -# Items -Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=鐵路調整工具@n@n左鍵單擊:切換軌道型別@n右鍵單擊:旋轉方塊 -Passive Component Naming Tool@n@nRight-click to name a passive component.=被動元件命名工具@n@n右鍵單擊命名所選元件 -Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=火車複製工具@n@n左鍵單擊:複製@n右鍵單擊:粘帖 -Track=軌道 -Perpendicular Diamond Crossing Track=垂直交叉軌道 -Diagonal Diamond Crossing Track=交叉軌道 -90+Angle Diamond Crossing Track=交叉軌道 (其中一條軌道與座標軸平行) -Y-turnout=對稱道岔 -3-way turnout=三開道岔 -Unloading Track=卸貨軌道 -Loading Track=裝貨軌道 -Bumper=保險槓 -Detector Rail=探測軌道 -@1 Slope=@1斜坡 -@1 Platform (low)=較低的@1月臺 -@1 Platform (high)=較高的@1月臺 -@1 Platform (low, 45 degree)=較低的@1月臺 (45°) -@1 Platform (45 degree)=較高的@1月臺 (45°) -Lampless Signal=臂木式號誌機 -Signal=色燈號誌機 -Wallmounted Signal (l)=壁掛式色燈號誌機 (左側) -Wallmounted Signal (r)=壁掛式色燈號誌機 (右側) -Wallmounted Signal (t)=懸掛式色燈號誌機 -Andrew's Cross=平交道號誌燈 -Boiler=鍋爐 -driver's cab=駕駛室 -Wheel=車輪 -Chimney=煙囪 - -# Seats -Default Seat=預設座位 -Default Seat (driver stand)=預設座位 (司機座位) -Driver stand=司機座位 -Driver Stand (left)=左側司機座位 -Driver Stand (right)=右側司機座位 - -# Wagon/engine types -Industrial Train Engine=工業用火車頭 -Big Industrial Train Engine=大型工業用火車頭 -Industrial tank wagon=液體運輸車廂 -Industrial wood wagon=木材運輸車廂 -Japanese Train Engine=高速列車車頭 -Japanese Train Wagon=高速列車車廂 -Steam Engine=蒸汽機車 -Detailed Steam Engine=精細的蒸汽機車 -Passenger Wagon=客車 -Box Wagon=貨運車廂 -Subway Passenger Wagon=地鐵車廂 diff --git a/advtrains/locale/gui b/advtrains/locale/gui deleted file mode 100755 index 7f455e4..0000000 --- a/advtrains/locale/gui +++ /dev/null @@ -1,638 +0,0 @@ -#!/usr/bin/tclsh -package require Tk - -# Auxiliary functions -proc maybe_lindex {lst idx fallback} { - set val [lindex $lst $idx] - if {$val eq {}} { - return $fallback - } else { - return $val - } -} - -proc firstupper {str} { - return [string cat [string toupper [string index $str 0]] [string range $str 1 end]] -} - -# CLI arguments -# NOTE: This will likely be changed in the future -set translationDomain [maybe_lindex $argv 0 "advtrains"] -set translationDir [maybe_lindex $argv 1 "."] - -# Translation file I/O, etc - -set translationTemplatePath [file join $translationDir "template.txt"] - -proc translationFilePaths {} { - global translationDir translationDomain - return [glob -path [file join $translationDir $translationDomain] ".*.tr"] -} - -proc readTranslationTemplate {} { - global translationTemplate translationTemplatePath - set translationTemplate [list] - set handle [open $translationTemplatePath "r"] - fconfigure $handle -translation lf - while {[gets $handle line] >= 0} { - if {$line eq ""} { - lappend translationTemplate $line - } elseif {[string match {#*} $line]} { - lappend translationTemplate $line - } elseif {[regexp {^(.+[^@])=.+$} $line x str]} { - lappend translationTemplate $str - } - } - close $handle -} - -proc readTranslationFiles {} { - global translationData translationLangs - array set translationData [list] - set translationLangs [list] - foreach fn [translationFilePaths] { - if {[regexp {\.([^.]+)\.tr$} $fn x lang]} { - set handle [open $fn "r"] - fconfigure $handle -translation lf - while {[gets $handle line] >= 0} { - if {[regexp {^([^#].+[^@])=(.+)$} $line x ori tr]} { - set translationData($lang,$ori) $tr - } - } - lappend translationLangs $lang - close $handle - } - } - set translationLangs [lsort $translationLangs] -} - -proc readTranslations {} { - readTranslationTemplate - readTranslationFiles -} - -proc writeTranslationTemplate {} { - global translationTemplate translationTemplatePath - set handle [open $translationTemplatePath "w"] - fconfigure $handle -translation lf - foreach line $translationTemplate { - if {$line eq ""} { - puts $handle "" - } elseif {[string match {#*} $line]} { - puts $handle $line - } else { - puts $handle "$line=$line" - } - } - close $handle -} - -proc writeTranslationFiles {} { - global translationDir translationDomain translationData translationLangs translationTemplate - foreach lang $translationLangs { - set handle [open [file join $translationDir "$translationDomain.$lang.tr"] "w"] - fconfigure $handle -translation lf - foreach i $translationTemplate { - if {$i eq ""} { - puts $handle "" - } elseif {[string match {#*} $i]} { - puts $handle $i - } else { - puts $handle [format "%s=%s" $i [getTranslationString $lang $i]] - } - } - close $handle - } -} - -proc writeTranslations {} { - writeTranslationTemplate - writeTranslationFiles -} - -proc hasTranslationString {lang str} { - return [expr {[getTranslationString $lang $str] ne $str}] -} - -proc maybeGetTranslationString {lang str} { - set tr [getTranslationString $lang $str] - if {$tr eq $str} { - return {} - } else { - return $tr - } -} - -proc getTranslationString {lang str} { - global translationData - if {[info exists translationData($lang,$str)]} { - return $translationData($lang,$str) - } else { - return $str - } -} - -proc setTranslationString {lang ori tr} { - global translationData - set translationData($lang,$ori) $tr -} - -proc rewordTranslationString {old new} { - global translationData translationLangs - foreach lang $translationLangs { - if {[hasTranslationString $lang $old]} { - setTranslationString $lang $new [getTranslationString $lang $old] - } else { - setTranslationString $lang $new $new - } - } -} - -# GUI helpers -proc gAddTab {basename title elems dummies} { - global gMainNotebook - gAddFrame $basename $elems $dummies - $gMainNotebook add "$gMainNotebook.$basename" -text $title -} - -proc gAddFrame {basename elems dummies} { - global gMainNotebook - set varbase [string cat "g" [firstupper $basename]] - set varname "${varbase}Frame" - set pathname "$gMainNotebook.$basename" - global $varname - set $varname $pathname - ttk::frame $pathname -padding 5 - foreach i $elems { - set varname [string cat $varbase [firstupper $i]] - global $varname - set $varname "$pathname.$i" - } - foreach i $dummies { - set varname [string cat $varbase [firstupper $i]] - global $varname - set $varname {} - } -} - -proc gReloadTranslations {} { - readTranslations - gTrLoadTranslations - gTmLoadTranslations -} - -proc gAddMenu {varname parent menuname entries} { - global $varname - set path "${parent}.${menuname}" - set $varname $path - $parent configure -menu [menu $path -tearoff false] - foreach i $entries { - $path add {*}$i - } - return $parent -} -set gMenuItemNotImplemented [list command -state disabled -label "(Not implemented)"] - -proc gNotImplemented {args} { - tk_messageBox -message "Not implemented" -icon error -type ok -} - -# Main window - -set gMainFrame ".f" -set gMainFrameWidgetCount 0 -foreach i [list readBtn writeBtn notebookTopSeparator notebook] { - set [string cat "gMain" [firstupper $i]] "$gMainFrame.$i" -} - -wm title . "Advtrains Translation File Editor" -grid rowconfigure . 0 -weight 1 -grid columnconfigure . 0 -weight 1 - -ttk::frame $gMainFrame -grid $gMainFrame -column 0 -row 0 -sticky nsew -grid rowconfigure $gMainFrame 2 -weight 1 - -foreach i [list \ - [ttk::button $gMainReadBtn -text "Reload translation files" -command gReloadTranslations] \ - [ttk::button $gMainWriteBtn -text "Write changes" -command writeTranslations] \ -] { - grid $i -column $gMainFrameWidgetCount -row 0 -sticky ns - incr gMainFrameWidgetCount -} - -grid columnconfigure $gMainFrame $gMainFrameWidgetCount -weight 1 - -ttk::separator $gMainNotebookTopSeparator -orient horizontal -grid $gMainNotebookTopSeparator -column 0 -row 1 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky ew - -ttk::notebook $gMainNotebook -grid $gMainNotebook -column 0 -row 2 -columnspan [expr {1+$gMainFrameWidgetCount}] -sticky nsew - -# Translation Manager -# FIXME?: it seems like Tcl requires -textvariable globals to be set first before they are accessible - -gAddTab tr "Translations" \ - [list langSelect refLangSelect readBtn writeBtn treeviewFrame origTextLabel origTextField translatedTextLabel translatedTextField refTextLabel refTextField] \ - [list langValue refLangValue origTextValue translatedTextValue refTextValue] -set gTrTreeview "$gTrTreeviewFrame.main" -set gTrTreeviewScrollbar "$gTrTreeviewFrame.scrollbar" - -grid rowconfigure $gTrFrame 0 -weight 1 -grid columnconfigure $gTrFrame 2 -weight 1 - -ttk::frame $gTrTreeviewFrame -borderwidth 1 -relief sunken -grid $gTrTreeviewFrame -column 0 -row 0 -columnspan 3 -sticky nsew -grid rowconfigure $gTrTreeviewFrame 0 -weight 1 -grid columnconfigure $gTrTreeviewFrame 0 -weight 1 -ttk::treeview $gTrTreeview -selectmode browse -columns {translation} -yscrollcommand {$gTrTreeviewScrollbar set} -grid $gTrTreeview -column 0 -row 0 -sticky nsew -bind $gTrTreeview <> gTrTreeviewSelectionCallback -ttk::scrollbar $gTrTreeviewScrollbar -orient vertical -command {$gTrTreeview yview} -grid $gTrTreeviewScrollbar -column 1 -row 0 -sticky ns -$gTrTreeview heading #0 -text "Original text" - -lmap i [list \ - [list \ - [ttk::label $gTrOrigTextLabel -text "Original" -anchor w] \ - {} \ - [ttk::entry $gTrOrigTextField -state readonly -textvariable gTrOrigTextValue] \ - ] \ - [list \ - [ttk::label $gTrTranslatedTextLabel -text "Translation" -anchor w] \ - [ttk::combobox $gTrLangSelect -exportselection false -state readonly -textvariable gTrLangValue] \ - [ttk::entry $gTrTranslatedTextField -textvariable gTrTranslatedTextValue] \ - ] \ - [list \ - [ttk::label $gTrRefTextLabel -text "Reference" -anchor w] \ - [ttk::combobox $gTrRefLangSelect -exportselection false -state readonly -textvariable gTrRefLangValue] \ - [ttk::entry $gTrRefTextField -state readonly -textvariable gTrRefTextValue] \ - ] \ -] row [list 1 2 3] { - lmap item $i col [list 0 1 2] { - if {$item eq ""} { - continue - } - grid $item -column $col -row $row -sticky nswe - } - grid rowconfigure $gTrFrame $row -uniform bottom - incr gTrRowCount -} - -bind $gTrLangSelect <> gTrLoadTranslationsToTreeview -trace add variable gTrTranslatedTextValue write gTrApplyTranslationString -bind $gTrRefLangSelect <> gTrTreeviewSelectionCallback - -proc gTrLoadTranslationsToTreeview {} { - global translationTemplate gTrTreeview gTrLangValue - $gTrTreeview heading translation -text "Translation: $gTrLangValue" - set prevFocus [$gTrTreeview item [$gTrTreeview focus] -text] - array set openedSections [list] - foreach i [$gTrTreeview children {}] { - if {[$gTrTreeview item $i -open]} { - set openedSections([$gTrTreeview item $i -text]) 1 - } - } - $gTrTreeview delete [$gTrTreeview children {}] - set parent {} - foreach i [lrange $translationTemplate 1 end] { - if {[regexp {^\#+\s*(.+)} $i x comment]} { - set parent [$gTrTreeview insert {} end -text $comment -tags {notranslate}] - if {[info exists openedSections($comment)]} { - $gTrTreeview item $parent -open true - } - if {$comment eq $prevFocus} { - $gTrTreeview focus $parent - $gTrTreeview selection set $parent - } - } elseif {$i ne ""} { - set last [$gTrTreeview insert $parent end -text $i -values [list [maybeGetTranslationString $gTrLangValue $i]]] - if {$i eq $prevFocus} { - $gTrTreeview focus $last - $gTrTreeview selection set $last - } - } - } - gTrTreeviewSelectionCallback -} - -proc gTrTreeviewSelectionCallback {} { - global gTrOrigTextValue gTrTreeview gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue gTrTranslatedTextField gTrTranslatedTextValue gTrRefTextField gTrRefTextValue - set focused [$gTrTreeview focus] - set gTrOrigTextValue [$gTrTreeview item $focused -text] - if {$focused eq ""} { - $gTrTranslatedTextField state disabled - $gTrRefTextField state disabled - set gTrTranslatedTextValue "Select an entry to translate" - set gTrRefTextValue "" - } elseif {[$gTrTreeview tag has notranslate $focused]} { - $gTrTranslatedTextField state disabled - $gTrRefTextField state disabled - set gTrTranslatedTextValue "Category names cannot be translated" - set gTrRefTextValue "" - } else { - $gTrTranslatedTextField state !disabled - set gTrTranslatedTextValue [maybeGetTranslationString $gTrLangValue $gTrOrigTextValue] - set gTrRefTextValue [maybeGetTranslationString $gTrRefLangValue $gTrOrigTextValue] - if {$gTrRefLangValue eq ""} { - $gTrRefTextField state disabled - set gTrRefTextValue "" - } elseif {$gTrRefTextValue eq ""} { - $gTrRefTextField state disabled - set gTrRefTextValue "The selected string is not yet translated to the reference language" - } else { - $gTrRefTextField state !disabled - } - } - $gTrLangSelect selection clear - $gTrRefLangSelect selection clear -} - -proc gTrLoadTranslations {} { - global translationLangs gTrLangSelect gTrLangValue gTrRefLangSelect gTrRefLangValue - set prevLang $gTrLangValue - set prevRefLang $gTrRefLangValue - $gTrLangSelect configure -values $translationLangs - $gTrRefLangSelect configure -values [linsert $translationLangs 0 ""] - if {[llength $translationLangs] < 1} { - tk_messageBox -icon error type ok -title "Error" -message "No translation files present." - exit 1 - } - if {$prevLang ni $translationLangs} { - $gTrLangSelect current 0 - } - if {$prevRefLang ni $translationLangs} { - $gTrRefLangSelect current 0 - } - gTrLoadTranslationsToTreeview -} - -proc gTrApplyTranslationString args { - global gTrTreeview gTrLangValue gTrOrigTextValue gTrTranslatedTextValue - set focused [$gTrTreeview focus] - if {![$gTrTreeview tag has notranslate $focused]} { - setTranslationString $gTrLangValue $gTrOrigTextValue $gTrTranslatedTextValue - $gTrTreeview item $focused -values [list $gTrTranslatedTextValue] - } -} - -# Translation Template Editor - -gAddTab tm "Template" \ - [list addStringMenuBtn addHeadingMenuBtn removeMenuBtn moveMenuBtn textField setMenuBtn treeviewFrame] \ - [list textValue] -set gTmTreeview "$gTmTreeviewFrame.main" -set gTmTreeviewScrollbar "$gTmTreeviewFrame.scrollbar" - -set gTmRowCount 0 -foreach i [list \ - [gAddMenu gTmAddStringMenu [ttk::menubutton $gTmAddStringMenuBtn -text "Add string"] "menu" [list \ - [list command -label "Insert before current entry" -command {gTmInsertStringAt true 0}] \ - [list command -label "Insert after current entry" -command {gTmInsertStringAt true 1}] \ - [list command -label "Insert as the first entry" -command {gTmInsertStringAt false 0}] \ - [list command -label "Insert as the last entry" -command {gTmInsertStringAt false end}] \ - ]] \ - [gAddMenu gTmAddHeadingMenu [ttk::menubutton $gTmAddHeadingMenuBtn -text "Add heading"] "menu" [list \ - [list command -label "Insert before current section" -command {gTmInsertHeadingAt true 0}] \ - [list command -label "Insert after current section" -command {gTmInsertHeadingAt true 1}] \ - ]] \ - [gAddMenu gTmRemoveMenu [ttk::menubutton $gTmRemoveMenuBtn -text "Remove"] "menu" [list \ - [list command -label "Remove entry" -command gTmDeleteEntry] \ - [list command -label "Remove section" -command gTmDeleteEntry] \ - [list command -label "Merge with previous section" -command gTmMergeWithPrevious] \ - ]] \ - [gAddMenu gTmMoveMenu [ttk::menubutton $gTmMoveMenuBtn -text "Move"] "menu" [list \ - [list command -label "Up" -command {gTmMoveInSection true -1}] \ - [list command -label "Down" -command {gTmMoveInSection true 1}] \ - [list command -label "To first" -command {gTmMoveInSection false 0}] \ - [list command -label "To last" -command {gTmMoveInSection false end}] \ - ]] \ -] { - grid $i -column 1 -row $gTmRowCount -sticky we - incr gTmRowCount -} - -ttk::frame $gTmTreeviewFrame -borderwidth 1 -relief sunken -grid $gTmTreeviewFrame -column 0 -row 0 -rowspan [expr {1+$gTmRowCount}] -sticky nsew -grid rowconfigure $gTmTreeviewFrame 0 -weight 1 -grid columnconfigure $gTmTreeviewFrame 0 -weight 1 -grid rowconfigure $gTmFrame $gTmRowCount -weight 1 -grid columnconfigure $gTmFrame 0 -weight 1 -ttk::treeview $gTmTreeview -selectmode browse -show tree -yscrollcommand {$gTmTreeviewScrollbar set} -bind $gTmTreeview <> gTmTreeviewSelectionCallback -grid $gTmTreeview -column 0 -row 0 -sticky nsew -ttk::scrollbar $gTmTreeviewScrollbar -orient vertical -command {$gTmTreeview yview} -grid $gTmTreeviewScrollbar -column 1 -row 0 -sticky ns -incr gTmRowCount - -ttk::entry $gTmTextField -textvariable gTmTextValue -grid $gTmTextField -column 0 -row $gTmRowCount -sticky nsew - -gAddMenu gTmSetMenu [ttk::menubutton $gTmSetMenuBtn -text "Set"] "menu" [list \ - [list command -label "Set heading" -command gTmSetEntry] \ - [list command -label "Set and copy translations" -command gTmSetEntryAndCopy] \ - [list command -label "Set without copying translations" -command gTmSetEntry] \ -] -grid $gTmSetMenuBtn -column 1 -row $gTmRowCount -sticky nsew - -proc gTmLoadTranslationsToTreeview {} { - global translationTemplate gTmTreeview - set prevFocus [$gTmTreeview item [$gTmTreeview focus] -text] - array set openedSections [list] - foreach i [$gTmTreeview children {}] { - if {[$gTmTreeview item $i -open]} { - set openedSections([$gTmTreeview item $i -text]) 1 - } - } - $gTmTreeview delete [$gTmTreeview children {}] - set parent {} - foreach i [lrange $translationTemplate 1 end] { - if {[regexp {^\#+\s*(.+)} $i x comment]} { - set parent [$gTmTreeview insert {} end -text $comment -tags {heading}] - if {[info exists openedSections($comment)]} { - $gTmTreeview item $parent -open true - } - if {$comment eq $prevFocus} { - $gTmTreeview focus $parent - $gTmTreeview selection set $parent - } - } elseif {$i ne ""} { - set last [$gTmTreeview insert $parent end -text $i] - if {$i eq $prevFocus} { - $gTmTreeview focus $last - $gTmTreeview selection set $last - } - } - } - gTmTreeviewSelectionCallback -} - -proc gTmTreeviewSelectionCallback {} { - global gTmTreeview gTmTextField gTmTextValue gTmAddStringMenu gTmAddHeadingMenu gTmRemoveMenu gTmMoveMenu gTmSetMenu - set focused [$gTmTreeview focus] - if {$focused eq {}} { - $gTmTextField state disabled - set gTmTextValue "Select an entry to edit" - foreach m [list $gTmAddStringMenu $gTmAddHeadingMenu $gTmRemoveMenu $gTmMoveMenu $gTmSetMenu] { - for {set i 0} {$i <= [$m index end]} {incr i} { $m entryconfigure $i -state disabled} - } - } else { - $gTmTextField state !disabled - set headingSetState disabled - set entrySetState normal - if {[$gTmTreeview tag has heading $focused]} { - set headingSetState normal - set entrySetState disabled - } - foreach ent [list \ - [list $gTmAddStringMenu \ - [list 0 -state $entrySetState] \ - [list 1 -state $entrySetState] \ - [list 2 -state normal] \ - [list 3 -state normal] \ - ] \ - [list $gTmAddHeadingMenu \ - [list 0 -state normal] \ - [list 1 -state normal] \ - ] \ - [list $gTmMoveMenu \ - [list 0 -state normal] \ - [list 1 -state normal] \ - [list 2 -state normal] \ - [list 3 -state normal] \ - ] \ - [list $gTmRemoveMenu \ - [list 0 -state $entrySetState] \ - [list 1 -state $headingSetState] \ - [list 2 -state $headingSetState] \ - ] \ - [list $gTmSetMenu \ - [list 0 -state $headingSetState] \ - [list 1 -state $entrySetState] \ - [list 2 -state $entrySetState] \ - ] \ - ] { - set m [lindex $ent 0] - lmap i [lrange $ent 1 end] { - $m entryconfigure {*}$i - } - } - set gTmTextValue [$gTmTreeview item $focused -text] - } -} - -proc gTmUpdateTemplateAux {parent} { - global translationTemplate gTmTreeview - foreach i [$gTmTreeview children $parent] { - set tval [$gTmTreeview item $i -text] - if {[$gTmTreeview tag has heading $i]} { - lappend translationTemplate {} - set tval "# $tval" - } - lappend translationTemplate $tval - gTmUpdateTemplateAux $i - } -} - -proc gTmUpdateTemplate {} { - global translationTemplate translationDomain - set translationTemplate [list "# textdomain: $translationDomain"] - gTmUpdateTemplateAux {} - gTrLoadTranslations - gTmLoadTranslationsToTreeview -} - -proc gTmSetEntry {} { - global gTmTreeview gTmTextValue - $gTmTreeview item [$gTmTreeview focus] -text $gTmTextValue - gTmUpdateTemplate -} - -proc gTmSetEntryAndCopy {} { - global gTmTreeview gTmTextValue - set focus [$gTmTreeview focus] - rewordTranslationString [$gTmTreeview item $focus -text] $gTmTextValue - gTmSetEntry -} - -proc gTmInsertStringAt {relative idx} { - global gTmTreeview - set focus [$gTmTreeview focus] - set parent [$gTmTreeview parent $focus] - set relidx [$gTmTreeview index $focus] - if {[$gTmTreeview tag has heading $focus]} { - set parent $focus - set relindex 0 - } - set newidx $idx - if {$relative} { - set newidx [expr {$idx+$relidx}] - } - set item [$gTmTreeview insert $parent $newidx -text {}] - $gTmTreeview focus $item - $gTmTreeview selection set $item -} - -proc gTmInsertHeadingAt {relative idx} { - global gTmTreeview - set focus [$gTmTreeview focus] - if {![$gTmTreeview tag has heading $focus]} { - set focus [$gTmTreeview parent $focus] - } - set parent [$gTmTreeview parent $focus] - set relidx [$gTmTreeview index $focus] - if {$focus eq {}} { - set parent {} - set relidx 0 - } - set newidx $idx - if {$relative} { - set newidx [expr {$idx+$relidx}] - } - set item [$gTmTreeview insert $parent $newidx -text {} -tags {heading}] - $gTmTreeview focus $item - $gTmTreeview selection set $item -} - -proc gTmMoveInSection {relative idx} { - global gTmTreeview - set focus [$gTmTreeview focus] - set parent [$gTmTreeview parent $focus] - set relidx [$gTmTreeview index $focus] - set newidx $idx - if {$relative} { - set newidx [expr {$idx+$relidx}] - } - $gTmTreeview move $focus $parent $newidx - gTmUpdateTemplate -} - -proc gTmDeleteEntry {} { - global gTmTreeview - $gTmTreeview delete [$gTmTreeview focus] - gTmUpdateTemplate -} - -proc gTmMergeWithPrevious {} { - global gTmTreeview - set parent [$gTmTreeview focus] - set prev [$gTmTreeview prev $parent] - set newindex end - if {$prev eq {}} { - set prev [$gTmTreeview parent $parent] - set newindex 0 - } - foreach i [$gTmTreeview children $parent] { - $gTmTreeview move $i $prev $newindex - } - $gTmTreeview delete $parent - gTmUpdateTemplate -} - -proc gTmLoadTranslations {} { - gTmLoadTranslationsToTreeview -} - -# Initialization - -gReloadTranslations diff --git a/advtrains/locale/template.txt b/advtrains/locale/template.txt deleted file mode 100644 index 8c8b859..0000000 --- a/advtrains/locale/template.txt +++ /dev/null @@ -1,146 +0,0 @@ -# textdomain: advtrains - -# Advtrains Core (unorganized) -This wagon is owned by @1, you can't destroy it.=This wagon is owned by @1, you can't destroy it. -Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.=Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon. -This position is protected!=This position is protected! -Can't place: not pointing at node=Can't place: not pointing at node -Can't place: space occupied!=Can't place: space occupied! -Can't place: protected position!=Can't place: protected position! -Can't place: Not enough slope items left (@1 required)=Can't place: Not enough slope items left (@1 required) -Can't place: There's no slope of length @1=Can't place: There's no slope of length @1 -Can't place: no supporting node at upper end.=Can't place: no supporting node at upper end. -Deprecated Track=Deprecated Track -Can't get on: wagon full or doors closed!=Can't get on: wagon full or doors closed! -Use Sneak+rightclick to bypass closed doors!=Use Sneak+rightclick to bypass closed doors! -Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off! -Access to @1=Access to @1 -You do not have the @1 privilege.=You do not have the @1 privilege. -The wagon's inventory is not empty!=The wagon's inventory is not empty! -Position is occupied by a train.=Position is occupied by a train. -There's a Track Circuit Break here.=There's a Track Circuit Break here. -There's a Signal Influence Point here.=There's a Signal Influence Point here. - -# Trackworker, rotation, adjustment -This node can't be rotated using the trackworker!=This node can't be rotated using the trackworker! -This node can't be changed using the trackworker!=This node can't be changed using the trackworker! -This track can not be changed!=This track can not be changed! -This track can not be rotated!=This track can not be rotated! -This track can not be removed!=This track can not be removed! - -# ATC -ATC controller, unconfigured.=ATC controller, unconfigured. -ATC controller=ATC controller -ATC controller, mode @1@nChannel: @2=ATC controller, mode @1@nChannel: @2 -ATC controller, mode @1@nCommand: @2=ATC controller, mode @1@nCommand: @2 -Command=Command -Command (on)=Command (on) -Digiline channel=Digiline channel -ATC Kick command warning: Doors closed=ATC Kick command warning: Doors closed -ATC Kick command warning: Train moving=ATC Kick command warning: Train moving -ATC Reverse command warning: didn't reverse train, train moving!=ATC Reverse command warning: didn't reverse train, train moving! -ATC command syntax error: I statement not closed: @1=ATC command syntax error: I statement not closed: @1 -ATC command parse error: Unknown command: @1=ATC command parse error: Unknown command: @1 - -# Coupling -Lock couples=Lock couples -You need to own at least one neighboring wagon to destroy this couple.=You need to own at least one neighboring wagon to destroy this couple. -Buffer and Chain Coupler=Buffer and Chain Coupler -Scharfenberg Coupler=Scharfenberg Coupler -Japanese Train Inter-Wagon Connection=Japanese Train Inter-Wagon Connection -Can not couple: The couplers of the trains do not match (@1 and @2).=Can not couple: The couplers of the trains do not match (@1 and @2). -You are not allowed to couple trains without the train_operator privilege.=You are not allowed to couple trains without the train_operator privilege. - -# Clipboard -The track you are trying to place the wagon on is not long enough!=The track you are trying to place the wagon on is not long enough! -The clipboard couldn't access the metadata. Paste failed.=The clipboard couldn't access the metadata. Paste failed. -The clipboard couldn't access the metadata. Copy failed.=The clipboard couldn't access the metadata. Copy failed. -The clipboard is empty.=The clipboard is empty. -Back of train would end up off track, cancelling.=Back of train would end up off track, cancelling. -No such lua entity!=No such lua entity! -No such wagon: @1=No such wagon: @1 -No such train: @1=No such train: @1 -Train copied!=Train copied! - -# Protection -You are not allowed to build tracks without the track_builder privilege.=You are not allowed to build tracks without the track_builder privilege. -You are not allowed to build near tracks without the track_builder privilege.=You are not allowed to build near tracks without the track_builder privilege. -You are not allowed to build tracks at this protected position.=You are not allowed to build tracks at this protected position. -You are not allowed to build near tracks at this protected position.=You are not allowed to build near tracks at this protected position. -You are not allowed to operate turnouts and signals without the railway_operator privilege.=You are not allowed to operate turnouts and signals without the railway_operator privilege. - -# Train HUD/Formspecs -Speed:=Speed: -Target:=Target: -Show Inventory=Show Inventory -Select seat:=Select seat: -Wagon properties=Wagon properties -Save wagon properties=Save wagon properties -Text displayed outside on train=Text displayed outside on train -Text displayed inside train=Text displayed inside train -Line=Line -Routingcode=Routingcode -Get off=Get off -Get off (forced)=Get off (forced) -(Doors closed)=(Doors closed) - -# General -Save=Save - -# Line automation -Station Code=Station Code -Station Name=Station Name -Door Delay=Door Delay -Door Side=Door Side -Dep. Speed=Dep. Speed -Stop Time=Stop Time - -# Items -Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc. -Passive Component Naming Tool@n@nRight-click to name a passive component.=Passive Component Naming Tool@n@nRight-click to name a passive component. -Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train=Train copy/paste tool@n@nLeft-click: copy train@nRight-click: paste train -Track=Track -Perpendicular Diamond Crossing Track=Perpendicular Diamond Crossing Track -Diagonal Diamond Crossing Track=Diagonal Diamond Crossing Track -90+Angle Diamond Crossing Track=90+Angle Diamond Crossing Track -Y-turnout=Y-turnout -3-way turnout=3-way turnout -Unloading Track=Unloading Track -Loading Track=Loading Track -Bumper=Bumper -Detector Rail=Detector Rail -@1 Slope=@1 Slope -@1 Platform (low)=@1 Platform (low) -@1 Platform (high)=@1 Platform (high) -@1 Platform (low, 45 degree)=@1 Platform (low, 45 degree) -@1 Platform (45 degree)=@1 Platform (45 degree) -Lampless Signal=Lampless Signal -Signal=Signal -Wallmounted Signal (l)=Wallmounted Signal (l) -Wallmounted Signal (r)=Wallmounted Signal (r) -Wallmounted Signal (t)=Wallmounted Signal (t) -Andrew's Cross=Andrew's Cross -Boiler=Boiler -driver's cab=driver's cab -Wheel=Wheel -Chimney=Chimney - -# Seats -Default Seat=Default Seat -Default Seat (driver stand)=Default Seat (driver stand) -Driver stand=Driver stand -Driver Stand (left)=Driver Stand (left) -Driver Stand (right)=Driver Stand (right) - -# Wagon/engine types -Industrial Train Engine=Industrial Train Engine -Big Industrial Train Engine=Big Industrial Train Engine -Industrial tank wagon=Industrial tank wagon -Industrial wood wagon=Industrial wood wagon -Japanese Train Engine=Japanese Train Engine -Japanese Train Wagon=Japanese Train Wagon -Steam Engine=Steam Engine -Detailed Steam Engine=Detailed Steam Engine -Passenger Wagon=Passenger Wagon -Box Wagon=Box Wagon -Subway Passenger Wagon=Subway Passenger Wagon diff --git a/advtrains/locale/topo.sh b/advtrains/locale/topo.sh deleted file mode 100755 index 23f81b1..0000000 --- a/advtrains/locale/topo.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -head -n18 ../po/template.pot | sed 's/charset=CHARSET/charset=UTF-8/' -sed -En 's/@n/\\n/g;s/@\n/\\n/g;s/\"/\\"/g;s/^([^=]+)=\1$/\1=/;s/^([^=]+)=([^=]*)$/\nmsgid "\1"\nmsgstr "\2"/gp' diff --git a/advtrains/po/README.md b/advtrains/po/README.md new file mode 100644 index 0000000..3e94682 --- /dev/null +++ b/advtrains/po/README.md @@ -0,0 +1,70 @@ +# Translations +Please read this document before working on any translations. + +Unlike many other mods, Advtrains uses `.po` files for localization, +which are then automatically converted to `.tr` files when the mod is +loaded. Therefore, please submit patches that edit the `.po` files. + +## Getting Started +The translation files can be edited like any other `.po` file. + +If the translation file for your language does not exist, create it by +copying `template.txt` to `advtrains.XX.tr`, where `XX` is replaced by +the language code. + +Feel free to use the [discussion mailing list][srht-discuss] if you +have any questions regarding localization. + +You can share your `.po` file directly or [as a patch][gsm] to the [dev +mailing list][srht-devel]. The latter is encouraged, but, unlike code +changes, translation files sent directly are also accepted. + +[tr-format]: https://minetest.gitlab.io/minetest/translations/#translation-file-format +[srht-discuss]: https://lists.sr.ht/~gpcf/advtrains-discuss +[srht-devel]: https://lists.sr.ht/~gpcf/advtrains-devel +[gsm]: https://git-send-email.io + +## Translation Notes +* Translations should be consistent. You can use other entries or the +translations in Minetest as a reference. +* Translations do not have to fully correspond to the original text - +they only need to provide the same information. In particular, +translations do not need to have the same linguistical structure as the +original text. +* Replacement sequences (`@1`, `@2`, etc) should not be translated. +* Certain abbreviations or names, such as "Ks" or "Zs 3", should +generally not be translated. + +### (de) German +* Verwenden Sie die neue Rechtschreibung und die Sie-Form. +* Mit der deutschen Tastaturbelegung unter Linux können die +Anführungszeichen „“ mit AltGr-V bzw. AltGr-B eingegeben werden. + +### (zh) Chinese +(This section is written in English to avoid writing the note twice or +using only one of the variants, as most of this section applies to both +the traditional and simplified variants.) + +* Please use the 「」 quotation marks for Traditional Chinese and “” +for Simplified Chinese. +* Please use the fullwidth variants of: , 、 。 ? ! : ; +* Please use the halfwidth variants of: ( ) [ ] / \ | +* Please do not leave any space between Han characters (including +fullwidth punctuation marks). +* Please leave a space between Han characters (excluding fullwidth +punctuation marks) and characters from other scripts (including +halfwidth punctuation marks). However, do not leave any space between +Han characters and Arabic numerals. + +## Notes for developers +* The `update-translations.sh` script can be used to update the +translation files. However, please make sure to install the +`basic_trains` mod before running the script. +* Please make sure that the first argument to `S` (or `attrans`) _only_ +includes string literals without formatting or concatenation. This is +unfortunately a limitation of the `xgettext` utility. +* Avoid word-by-word translations. +* Avoid manipulating translated strings (except for concatenation). Use +server-side translations if you have to modify the text sent to users. +* Avoid truncating strings unless multibyte characters are handled +properly. diff --git a/advtrains/poconvert.lua b/advtrains/poconvert.lua new file mode 100644 index 0000000..74f962e --- /dev/null +++ b/advtrains/poconvert.lua @@ -0,0 +1,185 @@ +local unescape_string +do + local schartbl = { -- https://en.wikipedia.org/wiki/Escape_sequences_in_C + a = "\a", + b = "\b", + e = string.char(0x1b), + f = "\f", + n = "\n", + r = "\r", + t = "\t", + v = "\v", + } + local function replace_single(pfx, c) + local pl = #pfx + if pl % 2 == 0 then + return string.sub(pfx, 1, pl/2) .. c + end + return string.sub(pfx, 1, math.floor(pl/2)) .. (schartbl[c] or c) + end + unescape_string = function(str) + return string.gsub(str, [[(\+)([abefnrtv'"?])]], replace_single) + end +end + +local function readstring_aux(str, pos) + local _, spos = string.find(str, [[^%s*"]], pos) + if not spos then + return nil + end + local ipos = spos + while true do + local _, epos, m = string.find(str, [[(\*)"]], ipos+1) + if not epos then + return error("String extends beyond the end of input") + end + ipos = epos + if #m % 2 == 0 then + return unescape_string(string.sub(str, spos+1, epos-1)), epos+1 + end + end +end + +local function readstring(str, pos) + local st = {} + local nxt = pos + while true do + local s, npos = readstring_aux(str, nxt) + if not s then + if not st[1] then + return nil, nxt + else + return table.concat(st), nxt + end + end + nxt = npos + table.insert(st, s) + end +end + +local function readtoken(str, pos) + local _, epos, tok = string.find(str, [[^%s*(%S+)]], pos) + if epos == nil then + return nil, pos + end + return tok, epos+1 +end + +local function readcomment_add_flags(flags, s) + for flag in string.gmatch(s, ",%s*([^,]+)") do + flags[flag] = true + end +end + +local function readcomment_aux(str, pos) + local _, epos, sval = string.find(str, "^\n*#([^\n]*)", pos) + if not epos then + return nil + end + return sval, epos+1 +end + +local function readcomment(str, pos) + local st = {} + local nxt = pos + local flags = {} + while true do + local s, npos = readcomment_aux(str, nxt) + if not npos then + local t = { + comment = table.concat(st, "\n"), + flags = flags, + } + return t, nxt + end + if string.sub(s, 1, 1) == "," then + readcomment_add_flags(flags, s) + end + table.insert(st, s) + nxt = npos + end +end + +local function readpo(str) + local st = {} + local pos = 1 + while true do + local entry, nxt = readcomment(str, pos) + local msglines = 0 + while true do + local tok, npos = readtoken(str, nxt) + if tok == nil or string.sub(tok, 1, 1) == "#" then + break + elseif string.sub(tok, 1, 3) ~= "msg" then + return error("Invalid token: " .. tok) + elseif entry[tok] ~= nil then + break + else + local value, npos = readstring(str, npos) + assert(value ~= nil, "No string provided for " .. tok) + entry[tok] = value + nxt = npos + msglines = msglines+1 + end + end + if msglines == 0 then + return st + elseif entry.msgid ~= "" then + assert(entry.msgid ~= nil, "Missing untranslated string") + assert(entry.msgstr ~= nil, "Missing translated string") + table.insert(st, entry) + end + pos = nxt + end +end + +local escape_lookup = { + ["="] = "@=", + ["\n"] = "@n" +} +local function escape_string(st) + return (string.gsub(st, "[=\n]", escape_lookup)) +end + +local function convert_po_string(textdomain, str) + local st = {string.format("# textdomain: %s", textdomain)} + for _, entry in ipairs(readpo(str)) do + local line = ("%s=%s"):format(escape_string(entry.msgid), escape_string(entry.msgstr)) + if entry.flags.fuzzy then + line = "#" .. line + end + table.insert(st, line) + end + return table.concat(st, "\n") +end + +local function convert_po_file(textdomain, inpath, outpath) + local f, err = io.open(inpath, "rb") + assert(f, err) + local str = convert_po_string(textdomain, f:read("*a")) + f:close() + minetest.safe_file_write(outpath, str) + return str +end + +local function convert_flat_po_directory(textdomain, modpath) + assert(textdomain, "No textdomain specified for po file conversion") + local mp = modpath or minetest.get_modpath(textdomain) + assert(mp ~= nil, "No path to write for " .. textdomain) + local popath = mp .. "/po" + local trpath = mp .. "/locale" + for _, infile in pairs(minetest.get_dir_list(popath, false)) do + local lang = string.match(infile, [[^([^%.]+)%.po$]]) + if lang then + local inpath = popath .. "/" .. infile + local outpath = ("%s/%s.%s.tr"):format(trpath, textdomain, lang) + convert_po_file(textdomain, inpath, outpath) + end + end +end + +return { + from_string = convert_po_string, + from_file = convert_po_file, + from_flat = convert_flat_po_directory, +} diff --git a/advtrains/spec/poconvert_spec.lua b/advtrains/spec/poconvert_spec.lua new file mode 100644 index 0000000..51f33e7 --- /dev/null +++ b/advtrains/spec/poconvert_spec.lua @@ -0,0 +1,70 @@ +package.path = "../?.lua;" .. package.path +advtrains = {} +_G.advtrains = advtrains +local poconvert = require("poconvert") + +describe("PO file converter", function() + it("should convert PO files", function() + assert.equals([[ +# textdomain: foo +foo=bar +baz= +#@=wh\at\\@n=@=w\as\\@n +multiline@nstrings=multiline@nresult +with context?=oder doch nicht]], poconvert.from_string("foo", [[ +msgid "" +msgstr "whatever metadata" + +msgid "foo" +msgstr "bar" + +msgid "baz" +msgstr "" + +#, fuzzy +msgid "=wh\\at\\\\\n" +msgstr "=w\\as\\\\\n" + +msgid "multi" +"line\n" +"strings" +msgstr "multi" +"line\n" +"result" + +msgctxt "i18n context" +msgid "with context?" +msgstr "oder doch nicht"]])) + end) + it("should reject invalid tokens", function() + assert.has.errors(function() + poconvert.from_string("", [[ +foo "" +bar ""]]) + end, "Invalid token: foo") + end) + it("should reject entries without a msgstr", function() + assert.has.errors(function() + poconvert.from_string("", [[msgid "foo"]]) + end, "Missing translated string") + end) + it("should reject entries without a msgid", function() + assert.has.errors(function() + poconvert.from_string("", [[msgstr "foo"]]) + end, "Missing untranslated string") + end) + it("should reject entries with improperly enclosed strings", function() + assert.has.errors(function() + poconvert.from_string("", [[ +msgid "foo" +msgstr "bar \]]) + end, "String extends beyond the end of input") + end) + it("should reject incomplete input", function() + assert.has.errors(function() + poconvert.from_string("", [[ +msgid "foo" +msgstr]]) + end, "No string provided for msgstr") + end) +end) -- cgit v1.2.3 From b075d8e3336dfb2755dd1b9dc29c5320a155013b Mon Sep 17 00:00:00 2001 From: "Y. Wang" Date: Fri, 20 Sep 2024 12:45:20 +0000 Subject: Implement staticdata for trains This patch exposes train.staticdata that can be used by other modders to save data in trains across restarts. It additionally exposes two new APIs for modders where this is relevant: * advtrains.te_register_on_couple(function(init_train, stat_train)): registers a callback for train coupling, where stat_train is couple into init_train and is subsequently removed. This callback is run before the actual coupling takes place; in particular, it is run before stat_train is removed. * advtrains.te_register_on_decouple(function(train, newtrain, index)): registers a callback for train decoupling, where newtrain is created by splitting the train at the given index (the wagon at the index is part of the new train). This callback is run after decoupling takes place. advtrains.te_register_on_decouple(function --- advtrains/couple.lua | 16 ++++++++++++++++ advtrains/init.lua | 1 + advtrains/trainlogic.lua | 6 ++++++ 3 files changed, 23 insertions(+) (limited to 'advtrains/init.lua') diff --git a/advtrains/couple.lua b/advtrains/couple.lua index 9474dcf..cbeb661 100644 --- a/advtrains/couple.lua +++ b/advtrains/couple.lua @@ -28,6 +28,20 @@ end advtrains.register_coupler_type("chain", attrans("Buffer and Chain Coupler")) advtrains.register_coupler_type("scharfenberg", attrans("Scharfenberg Coupler")) +for _, name in pairs {"couple", "decouple"} do + local t = {} + local function reg(f) + table.insert(t, f) + end + local function cb(...) + for _, f in ipairs(t) do + f(...) + end + end + advtrains["te_registered_on_" .. name] = t + advtrains["te_register_on_" .. name] = reg + advtrains["te_run_callbacks_on_" .. name] = cb +end local function create_couple_entity(pos, train1, t1_is_front, train2, t2_is_front) local id1 = train1.id @@ -235,6 +249,8 @@ function advtrains.couple_trains(init_train, invert_init_train, stat_train, stat return end + advtrains.te_run_callbacks_on_couple(init_train, stat_train) + if stat_train_opposite then -- insert wagons in inverse order and set their wagon_flipped state for i=1,stat_wagoncnt do diff --git a/advtrains/init.lua b/advtrains/init.lua index cb2214d..4a0b928 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -476,6 +476,7 @@ advtrains.avt_save = function(remove_players_from_wagons) "text_outside", "text_inside", "line", "routingcode", "il_sections", "speed_restriction", "speed_restrictions_t", "is_shunt", "points_split", "autocouple", "atc_wait_autocouple", "ars_disable", + "staticdata", }) --then save it tmp_trains[id]=v diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index 3b006d2..ed49a4c 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -263,6 +263,10 @@ function advtrains.train_ensure_init(id, train) atwarn(debug.traceback()) return nil end + + if not train.staticdata then + train.staticdata = {} + end train.dirty = true if train.no_step then @@ -1190,6 +1194,8 @@ function advtrains.split_train_at_index(train, index) newtrain.points_split = advtrains.merge_tables(train.points_split) newtrain.autocouple = train.autocouple + advtrains.te_run_callbacks_on_decouple(train, newtrain, index) + return newtrain_id -- return new train ID, so new train can be manipulated end -- cgit v1.2.3 From 49d177d82cb09d19e7a9f5731e316d1079546b28 Mon Sep 17 00:00:00 2001 From: orwell Date: Tue, 7 Jan 2025 23:29:53 +0100 Subject: Remove unused source files (parts of ywang's original distant signal implementation & old track registration) --- advtrains/init.lua | 1 - advtrains/oldtracks.lua | 751 ---------------------------------- advtrains/trackdb_legacy.lua | 27 -- advtrains_interlocking/aspect.lua | 296 -------------- advtrains_interlocking/distant_ui.lua | 141 ------- advtrains_interlocking/init.lua | 2 - 6 files changed, 1218 deletions(-) delete mode 100644 advtrains/oldtracks.lua delete mode 100644 advtrains/trackdb_legacy.lua delete mode 100644 advtrains_interlocking/aspect.lua delete mode 100644 advtrains_interlocking/distant_ui.lua (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 3918ab3..ad66200 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -225,7 +225,6 @@ dofile(advtrains.modpath.."/atc.lua") dofile(advtrains.modpath.."/wagons.lua") dofile(advtrains.modpath.."/protection.lua") -dofile(advtrains.modpath.."/trackdb_legacy.lua") dofile(advtrains.modpath.."/nodedb.lua") dofile(advtrains.modpath.."/couple.lua") diff --git a/advtrains/oldtracks.lua b/advtrains/oldtracks.lua deleted file mode 100644 index c415143..0000000 --- a/advtrains/oldtracks.lua +++ /dev/null @@ -1,751 +0,0 @@ ---advtrains by orwell96, see readme.txt - ---dev-time settings: ---EDIT HERE ---If the old non-model rails on straight tracks should be replaced by the new... ---false: no ---true: yes -advtrains.register_replacement_lbms=false - ---[[TracksDefinition -nodename_prefix -texture_prefix -description -common={} -straight={} -straight45={} -curve={} -curve45={} -lswitchst={} -lswitchst45={} -rswitchst={} -rswitchst45={} -lswitchcr={} -lswitchcr45={} -rswitchcr={} -rswitchcr45={} -vert1={ - --you'll probably want to override mesh here -} -vert2={ - --you'll probably want to override mesh here -} -]]-- -advtrains.all_tracktypes={} - ---definition preparation -local function conns(c1, c2, r1, r2) return {{c=c1, y=r1}, {c=c2, y=r2}} end -local function conns3(c1, c2, c3, r1, r2, r3) return {{c=c1, y=r1}, {c=c2, y=r2}, {c=c3, y=r3}} end - -advtrains.ap={} -advtrains.ap.t_30deg_flat={ - regstep=1, - variant={ - st={ - conns = conns(0,8), - desc = "straight", - tpdouble = true, - tpsingle = true, - trackworker = "cr", - }, - cr={ - conns = conns(0,7), - desc = "curve", - tpdouble = true, - trackworker = "swlst", - }, - swlst={ - conns = conns3(0,8,7), - desc = "left switch (straight)", - trackworker = "swrst", - switchalt = "cr", - switchmc = "on", - switchst = "st", - switchprefix = "swl", - }, - swlcr={ - conns = conns3(0,7,8), - desc = "left switch (curve)", - trackworker = "swrcr", - switchalt = "st", - switchmc = "off", - switchst = "cr", - switchprefix = "swl", - }, - swrst={ - conns = conns3(0,8,9), - desc = "right switch (straight)", - trackworker = "st", - switchalt = "cr", - switchmc = "on", - switchst = "st", - switchprefix = "swr", - }, - swrcr={ - conns = conns3(0,9,8), - desc = "right switch (curve)", - trackworker = "st", - switchalt = "st", - switchmc = "off", - switchst = "cr", - switchprefix = "swr", - }, - }, - regtp=true, - tpdefault="st", - trackworker={ - ["swrcr"]="st", - ["swrst"]="st", - ["cr"]="swlst", - ["swlcr"]="swrcr", - ["swlst"]="swrst", - }, - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_yturnout={ - regstep=1, - variant={ - l={ - conns = conns3(0,7,9), - desc = "Y-turnout (left)", - switchalt = "r", - switchmc = "off", - switchst = "l", - switchprefix = "", - }, - r={ - conns = conns3(0,9,7), - desc = "Y-turnout (right)", - switchalt = "l", - switchmc = "on", - switchst = "r", - switchprefix = "", - } - }, - regtp=true, - tpdefault="l", - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_s3way={ - regstep=1, - variant={ - l={ - conns = { {c=0}, {c=7}, {c=8}, {c=9}, {c=0} }, - desc = "3-way turnout (left)", - switchalt = "s", - switchst="l", - switchprefix = "", - }, - s={ - conns = { {c=0}, {c=8}, {c=7}, {c=9}, {c=0} }, - desc = "3-way turnout (straight)", - switchalt ="r", - switchst = "s", - switchprefix = "", - }, - r={ - conns = { {c=0}, {c=9}, {c=8}, {c=7}, {c=0} }, - desc = "3-way turnout (right)", - switchalt = "l", - switchst="r", - switchprefix = "", - } - }, - regtp=true, - tpdefault="l", - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_30deg_slope={ - regstep=1, - variant={ - vst1={conns = conns(8,0,0,0.5), rail_y = 0.25, desc = "steep uphill 1/2", slope=true}, - vst2={conns = conns(8,0,0.5,1), rail_y = 0.75, desc = "steep uphill 2/2", slope=true}, - vst31={conns = conns(8,0,0,0.33), rail_y = 0.16, desc = "uphill 1/3", slope=true}, - vst32={conns = conns(8,0,0.33,0.66), rail_y = 0.5, desc = "uphill 2/3", slope=true}, - vst33={conns = conns(8,0,0.66,1), rail_y = 0.83, desc = "uphill 3/3", slope=true}, - }, - regsp=true, - slopeplacer={ - [2]={"vst1", "vst2"}, - [3]={"vst31", "vst32", "vst33"}, - max=3,--highest entry - }, - slopeplacer_45={ - [2]={"vst1_45", "vst2_45"}, - max=2, - }, - rotation={"", "_30", "_45", "_60"}, - trackworker={}, - increativeinv={}, -} -advtrains.ap.t_30deg_straightonly={ - regstep=1, - variant={ - st={ - conns = conns(0,8), - desc = "straight", - tpdouble = true, - tpsingle = true, - trackworker = "st", - }, - }, - regtp=true, - tpdefault="st", - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_30deg_straightonly_noplacer={ - regstep=1, - variant={ - st={ - conns = conns(0,8), - desc = "straight", - tpdouble = true, - tpsingle = true, - trackworker = "st", - }, - }, - tpdefault="st", - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_45deg={ - regstep=2, - variant={ - st={ - conns = conns(0,8), - desc = "straight", - tpdouble = true, - tpsingle = true, - trackworker = "cr", - }, - cr={ - conns = conns(0,6), - desc = "curve", - tpdouble = true, - trackworker = "swlst", - }, - swlst={ - conns = conns3(0,8,6), - desc = "left switch (straight)", - trackworker = "swrst", - switchalt = "cr", - switchmc = "on", - switchst = "st", - }, - swlcr={ - conns = conns3(0,6,8), - desc = "left switch (curve)", - trackworker = "swrcr", - switchalt = "st", - switchmc = "off", - switchst = "cr", - }, - swrst={ - conns = conns3(0,8,10), - desc = "right switch (straight)", - trackworker = "st", - switchalt = "cr", - switchmc = "on", - switchst = "st", - }, - swrcr={ - conns = conns3(0,10,8), - desc = "right switch (curve)", - trackworker = "st", - switchalt = "st", - switchmc = "off", - switchst = "cr", - }, - }, - regtp=true, - tpdefault="st", - trackworker={ - ["swrcr"]="st", - ["swrst"]="st", - ["cr"]="swlst", - ["swlcr"]="swrcr", - ["swlst"]="swrst", - }, - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_perpcrossing={ - regstep = 1, - variant={ - st={ - conns = { {c=0}, {c=8}, {c=4}, {c=12} }, - desc = "perpendicular crossing", - tpdouble = true, - tpsingle = true, - trackworker = "st", - }, - }, - regtp=true, - tpdefault="st", - rotation={"", "_30", "_45", "_60"}, -} -advtrains.ap.t_90plusx_crossing={ - regstep = 1, - variant={ - ["30l"]={ - conns = { {c=0}, {c=8}, {c=1}, {c=9} }, - desc = "30/90 degree crossing (left)", - tpdouble = true, - tpsingle = true, - trackworker = "45l" - }, - ["45l"]={ - conns = { {c=0}, {c=8}, {c=2}, {c=10} }, - desc = "45/90 degree crossing (left)", - tpdouble = true, - tpsingle = true, - trackworker = "60l", - }, - ["60l"]={ - conns = { {c=0}, {c=8}, {c=3}, {c=11}}, - desc = "60/90 degree crossing (left)", - tpdouble = true, - tpsingle = true, - trackworker = "60r", - }, - ["60r"]={ - conns = { {c=0}, {c=8}, {c=5}, {c=13} }, - desc = "60/90 degree crossing (right)", - tpdouble = true, - tpsingle = true, - trackworker = "45r" - }, - ["45r"]={ - conns = { {c=0}, {c=8}, {c=6}, {c=14} }, - desc = "45/90 degree crossing (right)", - tpdouble = true, - tpsingle = true, - trackworker = "30r", - }, - ["30r"]={ - conns = { {c=0}, {c=8}, {c=7}, {c=15}}, - desc = "30/90 degree crossing (right)", - tpdouble = true, - tpsingle = true, - trackworker = "30l", - }, - }, - regtp=true, - tpdefault="30l", - rotation={""}, - trackworker = { - ["30l"] = "45l", - ["45l"] = "60l", - ["60l"] = "60r", - ["60r"] = "45r", - ["45r"] = "30r", - ["30r"] = "30l", - } -} - -advtrains.ap.t_diagonalcrossing = { - regstep=1, - variant={ - ["30l45r"]={ - conns = {{c=1}, {c=9}, {c=6}, {c=14}}, - desc = "30left-45right diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="60l30l", - }, - ["60l30l"]={ - conns = {{c=3}, {c=11}, {c=1}, {c=9}}, - desc = "30left-60right diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="60l45r" - }, - ["60l45r"]={ - conns = {{c=3}, {c=11}, {c=6}, {c=14}}, - desc = "60left-45right diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="60l60r" - }, - ["60l60r"]={ - conns = {{c=3}, {c=11}, {c=5}, {c=13}}, - desc = "60left-60right diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="60r45l", - }, - --If 60l60r had a mirror image, it would be here, but it's symmetric. - -- 60l60r is also equivalent to 30l30r but rotated 90 degrees. - ["60r45l"]={ - conns = {{c=5}, {c=13}, {c=2}, {c=10}}, - desc = "60right-45left diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="60r30r", - }, - ["60r30r"]={ - conns = {{c=5}, {c=13}, {c=7}, {c=15}}, - desc = "60right-30right diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="30r45l", - }, - ["30r45l"]={ - conns = {{c=7}, {c=15}, {c=2}, {c=10}}, - desc = "30right-45left diagonal crossing", - tpdouble=true, - tpsingle=true, - trackworker="30l45r", - }, - - }, - regtp=true, - tpdefault="30l45r", - rotation={""}, - trackworker = { - ["30l45r"] = "60l30l", - ["60l30l"] = "60l45r", - ["60l45r"] = "60l60r", - ["60l60r"] = "60r45l", - ["60r45l"] = "60r30r", - ["60r30r"] = "30r45l", - ["30r45l"] = "30l45r", - } -} - -advtrains.trackpresets = advtrains.ap - ---definition format: ([] optional) ---[[{ - nodename_prefix - texture_prefix - [shared_texture] - models_prefix - models_suffix (with dot) - [shared_model] - formats={ - st,cr,swlst,swlcr,swrst,swrcr,vst1,vst2 - (each a table with indices 0-3, for if to register a rail with this 'rotation' table entry. nil is assumed as 'all', set {} to not register at all) - } - common={} change something on common rail appearance -} -[18.12.17] Note on new connection system: -In order to support real rail crossing nodes and finally make the trackplacer respect switches, I changed the connection system. -There can be a variable number of connections available. These are specified as tuples {c=, y=} -The table "at_conns" consists of {, ...} -the "at_rail_y" property holds the value that was previously called "railheight" -Depending on the number of connections: -2 conns: regular rail -3 conns: switch: - - when train passes in at conn1, will move out of conn2 - - when train passes in at conn2 or conn3, will move out of conn1 -4 conns: cross (or cross switch, depending on arrangement of conns): - - conn1 <> conn2 - - conn3 <> conn4 -]] - --- Notify the user if digging the rail is not allowed -local function can_dig_callback(pos, player) - local ok, reason = advtrains.can_dig_or_modify_track(pos) - if not ok and player then - minetest.chat_send_player(player:get_player_name(), attrans("This track can not be removed!") .. " " .. reason) - end - return ok -end - -function advtrains.register_tracks(tracktype, def, preset) - advtrains.trackplacer.register_tracktype(def.nodename_prefix, preset.tpdefault) - if preset.regtp then - advtrains.trackplacer.register_track_placer(def.nodename_prefix, def.texture_prefix, def.description, def) - end - if preset.regsp then - advtrains.slope.register_placer(def, preset) - end - for suffix, var in pairs(preset.variant) do - for rotid, rotation in ipairs(preset.rotation) do - if not def.formats[suffix] or def.formats[suffix][rotid] then - local img_suffix = suffix..rotation - local ndef = advtrains.merge_tables({ - description=def.description.."("..(var.desc or "any")..rotation..")", - drawtype = "mesh", - paramtype="light", - paramtype2="facedir", - walkable = false, - selection_box = { - type = "fixed", - fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2}, - }, - - mesh = def.shared_model or (def.models_prefix.."_"..img_suffix..def.models_suffix), - tiles = {def.shared_texture or (def.texture_prefix.."_"..img_suffix..".png"), def.second_texture}, - - groups = { - attached_node = advtrains.IGNORE_WORLD and 0 or 1, - advtrains_track=1, - ["advtrains_track_"..tracktype]=1, - save_in_at_nodedb=1, - dig_immediate=2, - not_in_creative_inventory=1, - not_blocking_trains=1, - }, - - can_dig = can_dig_callback, - after_dig_node=function(pos) - advtrains.ndb.update(pos) - end, - after_place_node=function(pos) - advtrains.ndb.update(pos) - end, - at_nnpref = def.nodename_prefix, - at_suffix = suffix, - at_rotation = rotation, - at_rail_y = var.rail_y - }, def.common or {}) - - if preset.regtp then - ndef.drop = def.nodename_prefix.."_placer" - end - if preset.regsp and var.slope then - ndef.drop = def.nodename_prefix.."_slopeplacer" - end - - --connections - ndef.at_conns = advtrains.rotate_conn_by(var.conns, (rotid-1)*preset.regstep) - - local ndef_avt_table - - if var.switchalt and var.switchst then - local switchfunc=function(pos, node, newstate) - newstate = newstate or var.switchalt -- support for 3 (or more) state switches - -- this code is only called from the internal setstate function, which - -- ensures that it is safe to switch the turnout - if newstate~=var.switchst then - advtrains.ndb.swap_node(pos, {name=def.nodename_prefix.."_"..(var.switchprefix or "")..newstate..rotation, param2=node.param2}) - advtrains.invalidate_all_paths(pos) - end - end - ndef.on_rightclick = function(pos, node, player) - if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then - advtrains.setstate(pos, nil, node) - advtrains.log("Switch", player:get_player_name(), pos) - end - end - if var.switchmc then - ndef.mesecons = {effector = { - ["action_"..var.switchmc] = function(pos, node) - advtrains.setstate(pos, nil, node) - end, - rules=advtrains.meseconrules - }} - end - ndef_avt_table = { - getstate = var.switchst, - setstate = switchfunc, - } - end - - local adef={} - if def.get_additional_definiton then - adef=def.get_additional_definiton(def, preset, suffix, rotation) - end - ndef = advtrains.merge_tables(ndef, adef) - - -- insert getstate/setstate functions after merging the additional definitions - if ndef_avt_table then - ndef.advtrains = advtrains.merge_tables(ndef.advtrains or {}, ndef_avt_table) - end - - minetest.register_node(":"..def.nodename_prefix.."_"..suffix..rotation, ndef) - --trackplacer - if preset.regtp then - local tpconns = {conn1=ndef.at_conns[1].c, conn2=ndef.at_conns[2].c} - if var.tpdouble then - advtrains.trackplacer.add_double_conn(def.nodename_prefix, suffix, rotation, tpconns) - end - if var.tpsingle then - advtrains.trackplacer.add_single_conn(def.nodename_prefix, suffix, rotation, tpconns) - end - end - advtrains.trackplacer.add_worked(def.nodename_prefix, suffix, rotation, var.trackworker) - end - end - end - advtrains.all_tracktypes[tracktype]=true -end - -function advtrains.is_track_and_drives_on(nodename, drives_on_p) - local drives_on = drives_on_p - if not drives_on then drives_on = advtrains.all_tracktypes end - local hasentry = false - for _,_ in pairs(drives_on) do - hasentry=true - end - if not hasentry then drives_on = advtrains.all_tracktypes end - - if not minetest.registered_nodes[nodename] then - return false - end - local nodedef=minetest.registered_nodes[nodename] - for k,v in pairs(drives_on) do - if nodedef.groups["advtrains_track_"..k] then - return true - end - end - return false -end - -function advtrains.get_track_connections(name, param2) - local nodedef=minetest.registered_nodes[name] - if not nodedef then atprint(" get_track_connections couldn't find nodedef for nodename "..(name or "nil")) return nil end - local noderot=param2 - if not param2 then noderot=0 end - if noderot > 3 then atprint(" get_track_connections: rail has invaild param2 of "..noderot) noderot=0 end - - local tracktype - for k,_ in pairs(nodedef.groups) do - local tt=string.match(k, "^advtrains_track_(.+)$") - if tt then - tracktype=tt - end - end - return advtrains.rotate_conn_by(nodedef.at_conns, noderot*AT_CMAX/4), (nodedef.at_rail_y or 0), tracktype -end - --- Function called when a track is about to be dug or modified by the trackworker --- Returns either true (ok) or false,"translated string describing reason why it isn't allowed" -function advtrains.can_dig_or_modify_track(pos) - if advtrains.get_train_at_pos(pos) then - return false, attrans("Position is occupied by a train.") - end - -- interlocking: tcb, signal IP a.s.o. - if advtrains.interlocking then - -- TCB? - if advtrains.interlocking.db.get_tcb(pos) then - return false, attrans("There's a Track Circuit Break here.") - end - -- signal ip? - if advtrains.interlocking.db.is_ip_at(pos, true) then -- is_ip_at with purge parameter - return false, attrans("There's a Signal Influence Point here.") - end - end - return true -end - --- slope placer. Defined in register_tracks. ---crafted with rail and gravel -local sl={} -function sl.register_placer(def, preset) - minetest.register_craftitem(":"..def.nodename_prefix.."_slopeplacer",{ - description = attrans("@1 Slope", def.description), - inventory_image = def.texture_prefix.."_slopeplacer.png", - wield_image = def.texture_prefix.."_slopeplacer.png", - groups={}, - on_place = sl.create_slopeplacer_on_place(def, preset) - }) -end ---(itemstack, placer, pointed_thing) -function sl.create_slopeplacer_on_place(def, preset) - return function(istack, player, pt) - if not pt.type=="node" then - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node")) - return istack - end - local pos=pt.above - if not pos then - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: not pointing at node")) - return istack - end - local node=minetest.get_node(pos) - if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to then - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: space occupied!")) - return istack - end - if not advtrains.check_track_protection(pos, player:get_player_name()) then - minetest.record_protection_violation(pos, player:get_player_name()) - return istack - end - --determine player orientation (only horizontal component) - --get_look_horizontal may not be available - local yaw=player.get_look_horizontal and player:get_look_horizontal() or (player:get_look_yaw() - math.pi/2) - - --rounding unit vectors is a nice way for selecting 1 of 8 directions since sin(30°) is 0.5. - local dirvec={x=math.floor(math.sin(-yaw)+0.5), y=0, z=math.floor(math.cos(-yaw)+0.5)} - --translate to direction to look up inside the preset table - local param2, rot45=({ - [-1]={ - [-1]=2, - [0]=3, - [1]=3, - }, - [0]={ - [-1]=2, - [1]=0, - }, - [1]={ - [-1]=1, - [0]=1, - [1]=0, - }, - })[dirvec.x][dirvec.z], dirvec.x~=0 and dirvec.z~=0 - local lookup=preset.slopeplacer - if rot45 then lookup=preset.slopeplacer_45 end - - --go unitvector forward and look how far the next node is - local step=1 - while step<=lookup.max do - local node=minetest.get_node(vector.add(pos, dirvec)) - --next node solid? - if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].buildable_to or advtrains.is_protected(pos, player:get_player_name()) then - --do slopes of this distance exist? - if lookup[step] then - if minetest.settings:get_bool("creative_mode") or istack:get_count()>=step then - --start placing - local placenodes=lookup[step] - while step>0 do - minetest.set_node(pos, {name=def.nodename_prefix.."_"..placenodes[step], param2=param2}) - if not minetest.settings:get_bool("creative_mode") then - istack:take_item() - end - step=step-1 - pos=vector.subtract(pos, dirvec) - end - else - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: Not enough slope items left (@1 required)", step)) - end - else - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: There's no slope of length @1",step)) - end - return istack - end - step=step+1 - pos=vector.add(pos, dirvec) - end - minetest.chat_send_player(player:get_player_name(), attrans("Can't place: no supporting node at upper end.")) - return itemstack - end -end - -advtrains.slope=sl - ---END code, BEGIN definition ---definition format: ([] optional) ---[[{ - nodename_prefix - texture_prefix - [shared_texture] - models_prefix - models_suffix (with dot) - [shared_model] - formats={ - st,cr,swlst,swlcr,swrst,swrcr,vst1,vst2 - (each a table with indices 0-3, for if to register a rail with this 'rotation' table entry. nil is assumed as 'all', set {} to not register at all) - } - common={} change something on common rail appearance -}]] - - - - - - - - - diff --git a/advtrains/trackdb_legacy.lua b/advtrains/trackdb_legacy.lua deleted file mode 100644 index 99349e8..0000000 --- a/advtrains/trackdb_legacy.lua +++ /dev/null @@ -1,27 +0,0 @@ ---trackdb_legacy.lua ---loads the (old) track database. the only use for this is to provide data for rails that haven't been written into the ndb database. ---nothing will be saved. ---if the user thinks that he has loaded every track in his world at least once, he can delete the track database. - ---trackdb[[y][x][z]={conn1, conn2, rely1, rely2, railheight} - - ---trackdb keeps its own save file. -advtrains.fpath_tdb=minetest.get_worldpath().."/advtrains_trackdb2" -local file, err = io.open(advtrains.fpath_tdb, "r") -if not file then - atprint("Not loading a trackdb file.") -else - local tbl = minetest.deserialize(file:read("*a")) - if type(tbl) == "table" then - advtrains.trackdb=tbl - atprint("Loaded trackdb file.") - end - file:close() -end - - - - - - diff --git a/advtrains_interlocking/aspect.lua b/advtrains_interlocking/aspect.lua deleted file mode 100644 index c7d5c81..0000000 --- a/advtrains_interlocking/aspect.lua +++ /dev/null @@ -1,296 +0,0 @@ ---- Signal aspect handling. --- @module advtrains.interlocking.aspect - -local registered_groups = {} - -local default_aspect = { - main = false, - dst = false, - shunt = true, - proceed_as_main = false, -} - -local signal_aspect = {} - -local signal_aspect_metatable = { - __eq = function(asp1, asp2) - for _, k in pairs {"main", "dst", "shunt", "proceed_as_main"} do - local v1, v2 = (asp1[k] or false), (asp2[k] or false) - if v1 ~= v2 then - return false - end - end - if asp1.group and asp1.group == asp2.group then - return asp1.name == asp2.name - end - return true - end, - __index = function(asp, field) - local val = signal_aspect[field] - if val then - return val - end - val = default_aspect[field] - if val == nil then - return nil - end - local group = registered_groups[rawget(asp, "group")] - if group then - local aspdef = group.aspects[rawget(asp, "name")] - if aspdef[field] ~= nil then - val = aspdef[field] - end - end - return val - end, - __tostring = function(asp) - local st = {} - if asp.group and asp.name then - table.insert(st, ("%q in %q"):format(asp.name, asp.group)) - end - if asp.main then - table.insert(st, ("current %d"):format(asp.main)) - end - if asp.main ~= 0 then - if asp.dst then - table.insert(st, string.format("next %d", asp.dst)) - end - end - if asp.main ~= 0 and asp.proceed_as_main then - table.insert(st, "proceed as main") - end - return ("[%s]"):format(table.concat(st, ", ")) - end, -} - -local function quicknew(t) - return setmetatable(t, signal_aspect_metatable) -end - ---- Signal aspect class. --- @type signal_aspect - ---- Return a plain version of the signal aspect. --- @param[opt=false] raw Bypass metamethods when fetching signal aspects --- @return A plain copy of the signal aspect object. -function signal_aspect:plain(raw) - local t = {} - for _, k in pairs {"main", "dst", "shunt", "proceed_as_main", "group", "name"} do - local v - if raw then - v = rawget(self, k) - else - v = self[k] - end - t[k] = v - end - return t -end - ---- Create (or copy) a signal aspect object. --- Note that signal aspect objects can also be created by calling the `advtrains.interlocking.aspect` table. --- @return The newly created signal aspect object. -function signal_aspect:new() - if type(self) ~= "table" then - return quicknew{} - end - local newasp = {} - for _, k in pairs {"main", "dst"} do - if type(self[k]) == "table" then - if self[k].free then - newasp[k] = self[k].speed - else - newasp[k] = 0 - end - else - newasp[k] = self[k] - end - end - if type(self.shunt) == "table" then - newasp.shunt = self.shunt.free - newasp.proceed_as_main = self.shunt.proceed_as_main - else - newasp.shunt = self.shunt - end - for _, k in pairs {"group", "name"} do - newasp[k] = self[k] - end - return quicknew(newasp) -end - ---- Modify the signal aspect in-place to fit in the specific signal group. --- @param group The signal group. The `nil` indicates a generic group. --- @return The (now modified) signal aspect itself. -function signal_aspect:to_group(group) - local cg = self.group - local gdef = registered_groups[group] - if type(self.name) ~= "string" then - self.name = nil - end - if not gdef then - for k in pairs(default_aspect) do - rawset(self, k, self[k]) - end - self.group = nil - self.name = nil - return self - elseif cg == group and gdef.aspects[self.name] then - return self - end - local newidx = 1 - if self.main == 0 then - newidx = #gdef.aspects - end - local cgdef = registered_groups[cg] - if cgdef then - local idx = (cgdef.aspects[self.name] or {}).index - if idx then - if idx >= #cgdef.aspects then - idx = #gdef.aspects - elseif idx >= #gdef.aspects then - idx = #gdef.aspects-1 - end - newidx = idx - end - end - self.group = group - self.name = gdef.aspects[newidx][1] - return self -end - ---- Modify the signal aspect in-place to indicate a specific distant aspect. --- @param dst The distant aspect --- @param[opt=1] shift The phase shift of the current signal. --- @return The (now modified) signal aspect itself. -function signal_aspect:adjust_distant(dst, shift) - if (shift or -1) < 0 then - shift = 1 - end - if not dst then - self.dst = nil - return self - end - if self.main ~= 0 then - self.dst = dst.main - else - self.dst = nil - return self - end - local dgdef = registered_groups[dst.group] - if dgdef then - if self.group == dst.group and shift == 0 then - self.name = dst.name - else - local idx = (dgdef.aspects[dst.name] or {}).index - if idx then - idx = math.max(idx-shift, 1) - self.group = dst.group - self.name = dgdef.aspects[idx][1] - end - end - end - return self -end - ---- Signal groups. --- @section signal_group - ---- Register a signal group. --- @function register_group --- @param def The definition table. -local function register_group(def) - local t = {} - local name = def.name - if type(name) ~= "string" then - return error("Expected signal group name to be a string, got " .. type(name)) - elseif registered_groups[name] then - return error(string.format("Attempt to redefine signal group %q, previously defined in %s", name, registered_groups[name].defined)) - end - t.name = name - - t.defined = debug.getinfo(2, "S").short_src or "[?]" - - local label = def.label or name - if type(label) ~= "string" then - return error("Label is not a string") - end - t.label = label - - local mainasps = {} - for idx, asp in pairs(def.aspects) do - local idxtp = type(idx) - if idxtp == "string" then - local t = {} - t.name = idx - - local label = asp.label or idx - if type(label) ~= "string" then - return error("Aspect label is not a string") - end - t.label = label - - for _, k in pairs{"main", "dst", "shunt"} do - t[k] = asp[k] - end - - mainasps[idx] = t - end - end - if #def.aspects < 2 then - return error("Insufficient entries in signal aspect list") - end - for idx, asplist in ipairs(def.aspects) do - if type(asplist) ~= "table" then - asplist = {asplist} - else - asplist = table.copy(asplist) - end - if #asplist < 1 then - error("Invalid entry in signal aspect list") - end - for _, k in ipairs(asplist) do - if type(k) ~= "string" then - return error("Invalid signal aspect ID") - end - local asp = mainasps[k] - if not asp then - return error("Invalid signal aspect ID") - end - if asp.index ~= nil then - return error("Attempt to assign a signal aspect to multiple numeric indices") - end - asp.index = idx - end - mainasps[idx] = asplist - end - t.aspects = mainasps - - registered_groups[name] = t -end - ---- Get the definition of a signal group. --- @function get_group_definition --- @param name The name of the signal group. --- @return[1] The definition for the signal group (if present). --- @return[2] The nil constant (otherwise). -local function get_group_definition(name) - local t = registered_groups[name] - if t then - return table.copy(t) - else - return nil - end -end - -local lib = { - register_group = register_group, - get_group_definition = get_group_definition, -} - -local libmt = { - __call = function(_, ...) - return signal_aspect.new(...) - end, -} - -return setmetatable(lib, libmt) diff --git a/advtrains_interlocking/distant_ui.lua b/advtrains_interlocking/distant_ui.lua deleted file mode 100644 index bb66dc4..0000000 --- a/advtrains_interlocking/distant_ui.lua +++ /dev/null @@ -1,141 +0,0 @@ -local F = advtrains.formspec -local D = advtrains.distant -local I = advtrains.interlocking - -function I.make_short_dst_formspec_component(pos, x, y, w) - local main, set_by = D.get_main(pos) - if main then - local pts_main = minetest.pos_to_string(main) - local desc = attrans("The assignment is made with an unknown method.") - if set_by == "manual" then - desc = attrans("The assignment is made manually.") - elseif set_by == "routesetting" then - desc = attrans("The assignment is made by the routesetting system.") - end - return table.concat { - F.S_label(x, y, "This signal is a distant signal of @1.", pts_main), - F.label(x, y+0.5, desc), - F.S_button_exit(x, y+1, w/2-0.125, "dst_assign", "Reassign"), - F.S_button_exit(x+w/2+0.125, y+1, w/2-0.125, "dst_unassign", "Unassign"), - } - else - return table.concat { - F.S_label(x, y, "This signal is not assigned to a main signal."), - F.S_label(x, y+0.5, "The distant aspect of the signal is not used."), - F.S_button_exit(x, y+1, w, "dst_assign", "Assign") - } - end -end - -function I.make_dst_list_formspec_component(pos, x, y, w, h) - local ymid = y+0.25+h/2 - local dstlist = {} - for pos, _ in pairs(D.get_dst(pos)) do - table.insert(dstlist, minetest.pos_to_string(advtrains.decode_pos(pos))) - end - return table.concat { - F.S_label(x, y, "Distant signals:"), - F.textlist(x, y+0.5, w-1, h-0.5, "dstlist", dstlist), - F.image_button_exit(x+w-0.75, ymid-0.875, 0.75, 0.75, "cdb_add.png", "dst_add", ""), - F.image_button_exit(x+w-0.75, ymid+0.125, 0.75, 0.75, "cdb_clear.png", "dst_del", ""), - } -end - -function I.make_dst_formspec_component(pos, x, y, w, h) - return I.make_short_dst_formspec_component(pos, x, y, w, h) - .. I.make_dst_list_formspec_component(pos, x, y+2, w, h-2) -end - -function I.show_distant_signal_form(pos, pname) - return I.show_ip_form(pos, pname) -end - -local signal_pos = {} -local function init_signal_assignment(pname, pos) - if not minetest.check_player_privs(pname, "interlocking") then - minetest.chat_send_player(pname, attrans("This operation is not allowed without the @1 privilege.", "interlocking")) - return - end - if not D.appropriate_signal(pos) then - minetest.chat_send_player(pname, attrans("Incompatible signal.")) - return - end - signal_pos[pname] = pos - minetest.chat_send_player(pname, attrans("Please punch the signal to use as the main signal.")) -end - -local distant_pos = {} -local function init_distant_assignment(pname, pos) - if not minetest.check_player_privs(pname, "interlocking") then - minetest.send_chat_player(pname, attrans("This operation is now allowed without the @1 privilege.", "interlocking")) - return - end - if not D.appropriate_signal(pos) then - minetest.chat_send_player(pname, attrans("Incompatible signal.")) - return - end - distant_pos[pname] = pos - minetest.chat_send_player(pname, attrans("Please punch the signal to use as the distant signal.")) -end - -minetest.register_on_punchnode(function(pos, node, player, pointed_thing) - local pname = player:get_player_name() - if not minetest.check_player_privs(pname, "interlocking") then - return - end - local spos = signal_pos[pname] - local distant = false - if not spos then - spos = distant_pos[pname] - if not spos then - return - end - distant = true - end - signal_pos[pname] = nil - distant_pos[pname] = nil - local is_signal = minetest.get_item_group(node.name, "advtrains_signal") >= 2 - if not (is_signal and D.appropriate_signal(pos)) then - minetest.chat_send_player(pname, attrans("Incompatible signal.")) - return - end - minetest.chat_send_player(pname, attrans("Successfully assigned signal.")) - if distant then - D.assign(spos, pos, "manual") - else - D.assign(pos, spos, "manual") - end -end) - -local dstsel = {} - -function advtrains.interlocking.handle_dst_formspec_fields(pname, pos, fields) - if not (pos and minetest.check_player_privs(pname, "interlocking")) then - return - end - if fields.dst_unassign then - D.unassign_dst(pos) - elseif fields.dst_assign then - init_signal_assignment(pname, pos) - elseif fields.dst_add then - init_distant_assignment(pname, pos) - elseif fields.dstlist then - dstsel[pname] = minetest.explode_textlist_event(fields.dstlist).index - elseif fields.dst_del then - local selid = dstsel[pname] - if selid then - local dsts = D.get_dst(pos) - local pos - for p, _ in pairs(dsts) do - selid = selid-1 - if selid <= 0 then - pos = p - break - end - end - if pos then - D.unassign_dst(advtrains.decode_pos(pos)) - end - end - end -end diff --git a/advtrains_interlocking/init.lua b/advtrains_interlocking/init.lua index c3b1119..ee08c30 100644 --- a/advtrains_interlocking/init.lua +++ b/advtrains_interlocking/init.lua @@ -12,8 +12,6 @@ end local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELIM ---advtrains.interlocking.aspect = dofile(modpath.."aspect.lua") - dofile(modpath.."database.lua") dofile(modpath.."signal_api.lua") dofile(modpath.."signal_aspect_ui.lua") -- cgit v1.2.3 From d18f9b8fae8beed6bf2349bdf296db3f28e9cd90 Mon Sep 17 00:00:00 2001 From: orwell Date: Wed, 15 Jan 2025 23:25:56 +0100 Subject: Disable dump debug save --- advtrains/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index ad66200..fe29260 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -33,7 +33,7 @@ advtrains = {trains={}, player_to_train_mapping={}} -- =======================Development/debugging settings===================== -- DO NOT USE FOR NORMAL OPERATION -local DUMP_DEBUG_SAVE = true +local DUMP_DEBUG_SAVE = false -- dump the save files in human-readable format into advtrains_DUMP local GENERATE_ATRICIFIAL_LAG = false -- cgit v1.2.3 From c974e70fde21cb5484e1b19c1f60b82c3ac7f3eb Mon Sep 17 00:00:00 2001 From: orwell Date: Sun, 23 Mar 2025 22:01:28 +0100 Subject: Back up pre-2.5.0 version of interlocking save file for users who want to downgrade. To be reverted for next release --- advtrains/init.lua | 10 ++++++++++ advtrains_interlocking/database.lua | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index fe29260..0d76ec0 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -427,6 +427,16 @@ function advtrains.load_version_4() if il_save then advtrains.interlocking.db.load(il_save) end + + -- TODO 2.5.0 backwards compatibility fallback: Store the pre-v2.5.0 save file so that it can be reverted to if needed + local fallback_file = advtrains.fpath.."_interlocking.ls.pre250" + local file = io.open(fallback_file, "rb") + if file then + io.close(file) + else + atwarn("Backing up pre-2.5.0 version of Interlocking save file to",fallback_file," for potential downgrade to older versions") + os.rename(advtrains.fpath.."_interlocking.ls", fallback_file) + end end --== load lines == diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index d80fb76..844d350 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -100,7 +100,7 @@ function ildb.load(data) local lpos = minetest.string_to_pos(lpts) if lpos then local epos = advtrains.encode_pos(lpos) - atdebug("ILDB converting tcb",pts,"side",t_side,"route",t_route,"lock position format",lpts,"->",epos) + atdebug("ILDB converting tcb",pts,"side",t_side,"route",t_rnum,"lock position format",lpts,"->",epos) locks_n[epos] = state else -- already correct format -- cgit v1.2.3 From c08896f9f5cccc08f49f14944c1a9c0c8c0b5796 Mon Sep 17 00:00:00 2001 From: Tanavit Date: Wed, 26 Mar 2025 10:57:05 +0100 Subject: Translations improvement. File : - advtrains : init.lua wagons.lua - advtrains_line_automation : scheduler.lua stoprail.lua Actions : - Conversion of attrans() to S() - Insertion of S() function calls where needed. Miscellaneous : - Removing of personnal tries on update-translastions.sh which should not have been committed. # Third and last patch of a serie of three to be applied to the master branch of advtrains on commit #0b7fdc6 # # ATTENTION : # # 1. These patches come from a derivation of the l10n branch which, afaik, is not yet merged in the master branch. # I guess that applying these patches will shortcut the l10n branch. # 2. These patches contain translations strings of for the modification I proposed some month ago for basic_trains which, # afaik, are not yet merged in its master branch. --- advtrains/init.lua | 50 ++-- advtrains/po/advtrains.pot | 366 +++++++++++++++++++++++++--- advtrains/po/de.po | 400 +++++++++++++++++++++++++++---- advtrains/po/fr.po | 413 ++++++++++++++++++++++++++++---- advtrains/po/update-translations.sh | 1 - advtrains/po/zh_CN.po | 388 +++++++++++++++++++++++++++--- advtrains/po/zh_TW.po | 388 +++++++++++++++++++++++++++--- advtrains/wagons.lua | 121 +++++----- advtrains_line_automation/scheduler.lua | 2 +- advtrains_line_automation/stoprail.lua | 44 ++-- 10 files changed, 1870 insertions(+), 303 deletions(-) (limited to 'advtrains/init.lua') diff --git a/advtrains/init.lua b/advtrains/init.lua index 0d76ec0..91b2b58 100644 --- a/advtrains/init.lua +++ b/advtrains/init.lua @@ -73,7 +73,7 @@ end local no_action=false local function reload_saves() - atwarn("Restoring saved state in 1 second...") + atwarn(S("Restoring saved state in 1 second...")) no_action=true advtrains.lock_path_inval = false --read last save state and continue, as if server was restarted @@ -84,7 +84,7 @@ local function reload_saves() end minetest.after(1, function() advtrains.load() - atwarn("Reload successful!") + atwarn(S("Reload successful!")) advtrains.ndb.restore_all() end) end @@ -349,7 +349,7 @@ function advtrains.avt_load() end end for wid, _ in pairs(todel) do - atwarn("Removing unused wagon", wid, "from wagon_save table.") + atwarn(S("Removing unused wagon"), wid, S("from wagon_save table.")) advtrains.wagon_save[wid]=nil end else @@ -414,7 +414,7 @@ function advtrains.load_version_4() end end for wid, _ in pairs(todel) do - atwarn("Removing unused wagon", wid, "from wagon_save table.") + atwarn(S("Removing unused wagon"), wid, S("from wagon_save table.")) advtrains.wagon_save[wid]=nil end end @@ -502,7 +502,7 @@ advtrains.avt_save = function(remove_players_from_wagons) --then save it tmp_trains[id]=v else - atwarn("Train",id,"had no wagons left because of some bug. It is being deleted. Wave it goodbye!") + atwarn(S("Train"),id,S("had no wagons left because of some bug. It is being deleted. Wave it goodbye!")) advtrains.remove_train(id) end end @@ -583,7 +583,7 @@ advtrains.avt_save = function(remove_players_from_wagons) local succ, err = serialize_lib.save_atomic_multiple(parts_table, advtrains.fpath.."_", callbacks_table) if not succ then - atwarn("Saving failed: "..err) + atwarn(S("Saving failed: ")..err) else -- store version advtrains.save_component(4, "version") @@ -686,7 +686,7 @@ end function advtrains.save(remove_players_from_wagons) if not init_load then --wait... we haven't loaded yet?! - atwarn("Instructed to save() but load() was never called!") + atwarn(S("Instructed to save() but load() was never called!")) return end @@ -715,7 +715,7 @@ function advtrains.save(remove_players_from_wagons) end minetest.register_on_shutdown(function() if within_mainstep then - atwarn("Crash during advtrains main step - skipping the shutdown save operation to not save inconsistent data!") + atwarn(S("Crash during advtrains main step - skipping the shutdown save operation to not save inconsistent data!")) else advtrains.save() end @@ -727,10 +727,10 @@ end) minetest.register_chatcommand("at_empty_seats", { params = "", -- Short parameter description - description = "Detach all players, especially the offline ones, from all trains. Use only when no one serious is on a train.", -- Full description + description = S("Detach all players, especially the offline ones, from all trains. Use only when no one serious is on a train."), -- Full description privs = {train_operator=true, server=true}, -- Require the "privs" privilege to run func = function(name, param) - atwarn("Data is being saved. While saving, advtrains will remove the players from trains. Save files will be reloaded afterwards!") + atwarn(S("Data is being saved. While saving, advtrains will remove the players from trains. Save files will be reloaded afterwards!")) advtrains.save(true) reload_saves() end, @@ -739,60 +739,60 @@ minetest.register_chatcommand("at_empty_seats", minetest.register_chatcommand("at_reroute", { params = "", - description = "Delete all train routes, force them to recalculate", + description = S("Delete all train routes, force them to recalculate"), privs = {train_operator=true}, -- Only train operator is required, since this is relatively safe. func = function(name, param) advtrains.invalidate_all_paths() - return true, "Successfully invalidated train routes" + return true, S("Successfully invalidated train routes") end, }) minetest.register_chatcommand("at_whereis", { params = "", - description = "Returns the position of the train with the given id", + description = S("Returns the position of the train with the given id"), privs = {train_operator = true}, func = function(name,param) local train = advtrains.trains[param] if not train or not train.last_pos then - return false, "Train "..param.." does not exist or is invalid" + return false, S("Train ")..param..S(" does not exist or is invalid") else - return true, "Train "..param.." is at "..minetest.pos_to_string(train.last_pos) + return true, S("Train ")..param..S(" is at ")..minetest.pos_to_string(train.last_pos) end end, }) minetest.register_chatcommand("at_tp", { params = "", - description = "Teleports you to the position of the train with the given id", + description = S("Teleports you to the position of the train with the given id"), privs = {train_operator = true, teleport = true}, func = function(name,param) local train = advtrains.trains[param] if not train or not train.last_pos then - return false, "Train "..param.." does not exist or is invalid" + return false, S("Train ")..param..S(" does not exist or is invalid") else minetest.get_player_by_name(name):set_pos(train.last_pos) - return true, "Teleporting to train "..param + return true, S("Teleporting to train ")..param end end, }) minetest.register_chatcommand("at_disable_step", { params = "", - description = "Disable the advtrains globalstep temporarily", + description = S("Disable the advtrains globalstep temporarily"), privs = {server=true}, func = function(name, param) if minetest.is_yes(param) then -- disable everything, and turn off saving no_action = true; - atwarn("The advtrains globalstep has been disabled. Trains are not moving, and no data is saved! Run '/at_disable_step no' to enable again!") - return true, "Disabled advtrains successfully" + atwarn(S("The advtrains globalstep has been disabled. Trains are not moving, and no data is saved! Run '/at_disable_step no' to enable again!")) + return true, S("Disabled advtrains successfully") elseif no_action then - atwarn("Re-enabling advtrains globalstep...") + atwarn(S("Re-enabling advtrains globalstep...")) reload_saves() return true else - return false, "Advtrains is already running normally!" + return false, S("Advtrains is already running normally!") end end, }) @@ -800,10 +800,10 @@ minetest.register_chatcommand("at_disable_step", minetest.register_chatcommand("at_status", { params = "", - description = "Print advtrains status info", + description = S("Print advtrains status info"), privs = {train_operator = true}, func = function(name, param) - return true, advtrains.print_concat_table({"Advtrains Status: no_action",no_action,"slowdown",advtrains.global_slowdown,"(log",math.log(advtrains.global_slowdown),")"}) + return true, advtrains.print_concat_table({S("Advtrains Status: no_action"),no_action,S("slowdown"),advtrains.global_slowdown,S("(log"),math.log(advtrains.global_slowdown),")"}) end, }) diff --git a/advtrains/po/advtrains.pot b/advtrains/po/advtrains.pot index ade6a33..cd6ea75 100644 --- a/advtrains/po/advtrains.pot +++ b/advtrains/po/advtrains.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: advtrains\n" "Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" -"POT-Creation-Date: 2024-12-08 15:21+0100\n" +"POT-Creation-Date: 2025-03-25 15:40+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -39,7 +39,8 @@ msgstr "" msgid "Digiline channel" msgstr "" -#: advtrains/atc.lua advtrains_line_automation/stoprail.lua +#: advtrains/atc.lua advtrains/wagons.lua +#: advtrains_line_automation/stoprail.lua #: advtrains_luaautomation/active_common.lua msgid "Save" msgstr "" @@ -149,6 +150,127 @@ msgstr "" msgid "Chimney" msgstr "" +#: advtrains/init.lua +msgid "Restoring saved state in 1 second..." +msgstr "" + +#: advtrains/init.lua +msgid "Reload successful!" +msgstr "" + +#: advtrains/init.lua +msgid "Removing unused wagon" +msgstr "" + +#: advtrains/init.lua +msgid "from wagon_save table." +msgstr "" + +#: advtrains/init.lua +msgid "Train" +msgstr "" + +#: advtrains/init.lua +msgid "" +"had no wagons left because of some bug. It is being deleted. Wave it goodbye!" +msgstr "" + +#: advtrains/init.lua +msgid "Saving failed: " +msgstr "" + +#: advtrains/init.lua +msgid "Instructed to save() but load() was never called!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Crash during advtrains main step - skipping the shutdown save operation to " +"not save inconsistent data!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Detach all players, especially the offline ones, from all trains. Use only " +"when no one serious is on a train." +msgstr "" + +#: advtrains/init.lua +msgid "" +"Data is being saved. While saving, advtrains will remove the players from " +"trains. Save files will be reloaded afterwards!" +msgstr "" + +#: advtrains/init.lua +msgid "Delete all train routes, force them to recalculate" +msgstr "" + +#: advtrains/init.lua +msgid "Successfully invalidated train routes" +msgstr "" + +#: advtrains/init.lua +msgid "Returns the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid " does not exist or is invalid" +msgstr "" + +#: advtrains/init.lua +msgid "Train " +msgstr "" + +#: advtrains/init.lua +msgid " is at " +msgstr "" + +#: advtrains/init.lua +msgid "Teleports you to the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "Teleporting to train " +msgstr "" + +#: advtrains/init.lua +msgid "Disable the advtrains globalstep temporarily" +msgstr "" + +#: advtrains/init.lua +msgid "" +"The advtrains globalstep has been disabled. Trains are not moving, and no " +"data is saved! Run '/at_disable_step no' to enable again!" +msgstr "" + +#: advtrains/init.lua +msgid "Disabled advtrains successfully" +msgstr "" + +#: advtrains/init.lua +msgid "Re-enabling advtrains globalstep..." +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains is already running normally!" +msgstr "" + +#: advtrains/init.lua +msgid "Print advtrains status info" +msgstr "" + +#: advtrains/init.lua +msgid "(log" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains Status: no_action" +msgstr "" + +#: advtrains/init.lua +msgid "slowdown" +msgstr "" + #: advtrains/misc_nodes.lua msgid "@1 Platform (low)" msgstr "" @@ -231,68 +353,64 @@ msgstr "" msgid "Andrew's Cross" msgstr "" -#: advtrains/trackplacer.lua -msgid "" -"Track Worker Tool\n" -"\n" -"Left-click: change rail type (straight/curve/switch)\n" -"Right-click: rotate object" -msgstr "" - -#: advtrains/trackplacer.lua -msgid "This node can't be rotated using the trackworker." +#: advtrains/track_reg_helper.lua advtrains/tracks.lua +msgid "This track can not be removed!" msgstr "" -#: advtrains/trackplacer.lua -msgid "This track can not be rotated." +#: advtrains/track_reg_helper.lua +msgid "@1 Slope" msgstr "" -#: advtrains/trackplacer.lua -msgid "This node can't be changed using the trackworker." +#: advtrains/track_reg_helper.lua +msgid "Can't place: not pointing at node" msgstr "" -#: advtrains/trackplacer.lua -msgid "This track can not be changed." +#: advtrains/track_reg_helper.lua +msgid "Can't place: space occupied!" msgstr "" -#: advtrains/tracks.lua -msgid "This track can not be removed." +#: advtrains/track_reg_helper.lua +msgid "Can't place: Not enough slope items left (@1 required)" msgstr "" -#: advtrains/tracks.lua -msgid "Position is occupied by a train." +#: advtrains/track_reg_helper.lua +msgid "Can't place: There's no slope of length @1" msgstr "" -#: advtrains/tracks.lua -msgid "There's a Track Circuit Break here." +#: advtrains/track_reg_helper.lua +msgid "Can't place: no supporting node at upper end." msgstr "" -#: advtrains/tracks.lua -msgid "There's a Signal Influence Point here." +#: advtrains/trackplacer.lua +msgid "" +"Track Worker Tool\n" +"\n" +"Left-click: change rail type (straight/curve/switch)\n" +"Right-click: rotate object" msgstr "" -#: advtrains/tracks.lua -msgid "@1 Slope" +#: advtrains/trackplacer.lua +msgid "This node can't be rotated using the trackworker!" msgstr "" -#: advtrains/tracks.lua -msgid "Can't place slope: not pointing at node." +#: advtrains/trackplacer.lua +msgid "This track can not be rotated!" msgstr "" -#: advtrains/tracks.lua -msgid "Can't place slope: space occupied." +#: advtrains/trackplacer.lua +msgid "This node can't be changed using the trackworker!" msgstr "" #: advtrains/tracks.lua -msgid "Can't place slope: Not enough slope items left (@1 required)." +msgid "Position is occupied by a train." msgstr "" #: advtrains/tracks.lua -msgid "Can't place slope: There's no slope of length @1." +msgid "There's a Track Circuit Break here." msgstr "" #: advtrains/tracks.lua -msgid "Can't place slope: no supporting node at upper end." +msgid "There's a Signal Influence Point here." msgstr "" #: advtrains/trainhud.lua @@ -313,10 +431,24 @@ msgstr "" msgid "Insufficient privileges to use this!" msgstr "" +#: advtrains/wagons.lua +msgid "Uninitialized init=" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized, removing" +msgstr "" + #: advtrains/wagons.lua msgid "This wagon is owned by @1, you can't destroy it." msgstr "" +#: advtrains/wagons.lua +msgid "" +"Destroying wagon with inventory, but inventory is not found? Shouldn't " +"happen!" +msgstr "" + #: advtrains/wagons.lua msgid "The wagon's inventory is not empty." msgstr "" @@ -331,6 +463,26 @@ msgid "" "sure, hold Sneak and left-click the wagon." msgstr "" +#: advtrains/wagons.lua +msgid " wagon:destroy(): data is not set!" +msgstr "" + +#: advtrains/wagons.lua +msgid "!!! Train off track !!!" +msgstr "" + +#: advtrains/wagons.lua +msgid " units" +msgstr "" + +#: advtrains/wagons.lua +msgid "Liquid: " +msgstr "" + +#: advtrains/wagons.lua +msgid "Liquid: empty" +msgstr "" + #: advtrains/wagons.lua msgid "Show Inventory" msgstr "" @@ -379,6 +531,30 @@ msgstr "" msgid "This Wagon ID" msgstr "" +#: advtrains/wagons.lua +msgid "Allow these players to access your wagon:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Wagon road number:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Freight Code:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Prev FC" +msgstr "" + +#: advtrains/wagons.lua +msgid "Current FC: " +msgstr "" + +#: advtrains/wagons.lua +msgid "Next FC:" +msgstr "" + #: advtrains/wagons.lua msgid "Save wagon properties" msgstr "" @@ -403,6 +579,22 @@ msgstr "" msgid "Routingcode" msgstr "" +#: advtrains/wagons.lua +msgid "Train overview /coupling control:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Train overview / coupling control is only shown when the train stands." +msgstr "" + +#: advtrains/wagons.lua +msgid "Remote Routesetting" +msgstr "" + +#: advtrains/wagons.lua +msgid "Clear 'Disable ARS' flag" +msgstr "" + #: advtrains/wagons.lua msgid "" "Doors are closed. Use Sneak+rightclick to ignore the closed doors and get " @@ -413,6 +605,46 @@ msgstr "" msgid "You are not allowed to access the driver stand." msgstr "" +#: advtrains/wagons.lua +msgid "Missing train_operator privilege" +msgstr "" + +#: advtrains/wagons.lua +msgid "Not allowed to do this." +msgstr "" + +#: advtrains/wagons.lua +msgid "You don't have the train_operator privilege." +msgstr "" + +#: advtrains/wagons.lua +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "" + +#: advtrains/wagons.lua +msgid "Please specify a player name to transfer ownership to." +msgstr "" + +#: advtrains/wagons.lua +msgid "That player does not exist!" +msgstr "" + +#: advtrains/wagons.lua +msgid "Not a valid wagon id." +msgstr "" + +#: advtrains/wagons.lua +msgid "That wagon does not exist!" +msgstr "" + +#: advtrains/wagons.lua +msgid "You have been given ownership of wagon @1" +msgstr "" + +#: advtrains/wagons.lua +msgid "Wagon @1 ownership changed from @2 to @3" +msgstr "" + #: advtrains_interlocking/routesetting.lua msgid "Route state changed." msgstr "" @@ -437,6 +669,10 @@ msgstr "" msgid "Point Speed Restriction Track" msgstr "" +#: advtrains_line_automation/scheduler.lua +msgid "No callback to handle schedule" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station Code" msgstr "" @@ -465,6 +701,18 @@ msgstr "" msgid "Door Side" msgstr "" +#: advtrains_line_automation/stoprail.lua +msgid "Closed" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Left" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Right" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Reverse train" msgstr "" @@ -473,6 +721,14 @@ msgstr "" msgid "Kick out passengers" msgstr "" +#: advtrains_line_automation/stoprail.lua +msgid "Wait for signal to clear" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Trains stopping here (ARS rules)" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station code \"@1\" already exists and is owned by @2." msgstr "" @@ -481,6 +737,14 @@ msgstr "" msgid "This station is owned by @1. You are not allowed to edit its name." msgstr "" +#: advtrains_line_automation/stoprail.lua +msgid "Unknown Station" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Next Stop:\n" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station/Stop Track" msgstr "" @@ -550,6 +814,38 @@ msgstr "" msgid "Set name of component (empty to clear)" msgstr "" +#: advtrains_signals_japan/init.lua +msgid "Japanese signal pole" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Clear (proceed)" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Reduced speed" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Caution" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Restricted speed" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Danger (halt)" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Distant Signal (" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Main Signal (" +msgstr "" + #: advtrains_train_industrial/init.lua advtrains_train_steam/init.lua msgid "Driver Stand (right)" msgstr "" diff --git a/advtrains/po/de.po b/advtrains/po/de.po index 8a7e009..458e701 100644 --- a/advtrains/po/de.po +++ b/advtrains/po/de.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: advtrains\n" "Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" -"POT-Creation-Date: 2024-12-08 15:21+0100\n" +"POT-Creation-Date: 2025-03-25 15:40+0100\n" "PO-Revision-Date: 2023-10-09 11:18+0200\n" "Last-Translator: Y. Wang \n" "Language-Team: German\n" @@ -58,7 +58,8 @@ msgstr "Befehl (wenn aktiviert)" msgid "Digiline channel" msgstr "Digiline-Kanal" -#: advtrains/atc.lua advtrains_line_automation/stoprail.lua +#: advtrains/atc.lua advtrains/wagons.lua +#: advtrains_line_automation/stoprail.lua #: advtrains_luaautomation/active_common.lua msgid "Save" msgstr "Speichern" @@ -162,6 +163,128 @@ msgstr "Führerstand" msgid "Wheel" msgstr "" +#: advtrains/init.lua +msgid " does not exist or is invalid" +msgstr "" + +#: advtrains/init.lua +msgid " is at " +msgstr "" + +#: advtrains/init.lua +msgid "(log" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains Status: no_action" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains is already running normally!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Crash during advtrains main step - skipping the shutdown save operation to " +"not save inconsistent data!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Data is being saved. While saving, advtrains will remove the players from " +"trains. Save files will be reloaded afterwards!" +msgstr "" + +#: advtrains/init.lua +msgid "Delete all train routes, force them to recalculate" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Detach all players, especially the offline ones, from all trains. Use only " +"when no one serious is on a train." +msgstr "" + +#: advtrains/init.lua +msgid "Disable the advtrains globalstep temporarily" +msgstr "" + +#: advtrains/init.lua +msgid "Disabled advtrains successfully" +msgstr "" + +#: advtrains/init.lua +msgid "Instructed to save() but load() was never called!" +msgstr "" + +#: advtrains/init.lua +msgid "Print advtrains status info" +msgstr "" + +#: advtrains/init.lua +msgid "Re-enabling advtrains globalstep..." +msgstr "" + +#: advtrains/init.lua +msgid "Reload successful!" +msgstr "" + +#: advtrains/init.lua +msgid "Removing unused wagon" +msgstr "" + +#: advtrains/init.lua +msgid "Restoring saved state in 1 second..." +msgstr "" + +#: advtrains/init.lua +msgid "Returns the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "Saving failed: " +msgstr "" + +#: advtrains/init.lua +msgid "Successfully invalidated train routes" +msgstr "" + +#: advtrains/init.lua +msgid "Teleporting to train " +msgstr "" + +#: advtrains/init.lua +msgid "Teleports you to the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "" +"The advtrains globalstep has been disabled. Trains are not moving, and no " +"data is saved! Run '/at_disable_step no' to enable again!" +msgstr "" + +#: advtrains/init.lua +msgid "Train" +msgstr "" + +#: advtrains/init.lua +#, fuzzy +msgid "Train " +msgstr "Der Zug wurde Kopiert." + +#: advtrains/init.lua +msgid "from wagon_save table." +msgstr "" + +#: advtrains/init.lua +msgid "" +"had no wagons left because of some bug. It is being deleted. Wave it goodbye!" +msgstr "" + +#: advtrains/init.lua +msgid "slowdown" +msgstr "" + #: advtrains/misc_nodes.lua msgid "@1 Platform (45 degree)" msgstr "Hoher @1-Bahnsteig (45°)" @@ -247,20 +370,59 @@ msgstr "An der rechten Seite montiertes Signal" msgid "Wallmounted Signal (top)" msgstr "An der Decke montiertes Signal" +#: advtrains/track_reg_helper.lua +msgid "@1 Slope" +msgstr "@1 Steigung" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "" +"Es kann nicht platziert werden: Sie haben nicht genug Steigungsblöcke, es " +"werden insgesamt @1 benötigt." + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: There's no slope of length @1" +msgstr "" +"Es kann nicht platziert werden: die Steigung der Länge @1 ist nicht " +"definiert." + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: no supporting node at upper end." +msgstr "" +"Es kann nicht platziert werden: es gibt keinen unterstützenden Block am Ende " +"der Steigung." + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: not pointing at node" +msgstr "Es kann nicht platziert werden: Sie zeigen nicht auf einem Block." + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: space occupied!" +msgstr "Es kann nicht platziert werden: Diese Position ist besetzt." + +#: advtrains/track_reg_helper.lua advtrains/tracks.lua +#, fuzzy +msgid "This track can not be removed!" +msgstr "Dieses Gleis kann nicht entfernt werden." + #: advtrains/trackplacer.lua -msgid "This node can't be changed using the trackworker." +#, fuzzy +msgid "This node can't be changed using the trackworker!" msgstr "Dieser Block kann nicht mit dem Gleiswerkzeug bearbeitet werden." #: advtrains/trackplacer.lua -msgid "This node can't be rotated using the trackworker." +#, fuzzy +msgid "This node can't be rotated using the trackworker!" msgstr "Dieser Block kann nicht mit dem Gleiswerkzeug gedreht werden." #: advtrains/trackplacer.lua -msgid "This track can not be changed." -msgstr "Dieses Gleis kann nicht geändert werden." - -#: advtrains/trackplacer.lua -msgid "This track can not be rotated." +#, fuzzy +msgid "This track can not be rotated!" msgstr "Dieses Gleis kann nicht gedreht werden." #: advtrains/trackplacer.lua @@ -275,36 +437,6 @@ msgstr "" "Linksklick: Gleistyp ändern\n" "Rechtsklick: Objekt drehen" -#: advtrains/tracks.lua -msgid "@1 Slope" -msgstr "@1 Steigung" - -#: advtrains/tracks.lua -msgid "Can't place slope: Not enough slope items left (@1 required)." -msgstr "" -"Es kann nicht platziert werden: Sie haben nicht genug Steigungsblöcke, es " -"werden insgesamt @1 benötigt." - -#: advtrains/tracks.lua -msgid "Can't place slope: There's no slope of length @1." -msgstr "" -"Es kann nicht platziert werden: die Steigung der Länge @1 ist nicht " -"definiert." - -#: advtrains/tracks.lua -msgid "Can't place slope: no supporting node at upper end." -msgstr "" -"Es kann nicht platziert werden: es gibt keinen unterstützenden Block am Ende " -"der Steigung." - -#: advtrains/tracks.lua -msgid "Can't place slope: not pointing at node." -msgstr "Es kann nicht platziert werden: Sie zeigen nicht auf einem Block." - -#: advtrains/tracks.lua -msgid "Can't place slope: space occupied." -msgstr "Es kann nicht platziert werden: Diese Position ist besetzt." - #: advtrains/tracks.lua msgid "Position is occupied by a train." msgstr "Ein Zug steht an dieser Position." @@ -317,10 +449,6 @@ msgstr "Hier ist ein Signal-Beeinflussungspunkt." msgid "There's a Track Circuit Break here." msgstr "Hier ist eine Gleisabschnittsgrenze (TCB)." -#: advtrains/tracks.lua -msgid "This track can not be removed." -msgstr "Dieses Gleis kann nicht entfernt werden." - #: advtrains/trainhud.lua msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." msgstr "" @@ -340,10 +468,40 @@ msgid "" "Punch a wagon to view and edit the Wagon Properties" msgstr "" +#: advtrains/wagons.lua +msgid " units" +msgstr "" + +#: advtrains/wagons.lua +msgid " wagon:destroy(): data is not set!" +msgstr "" + +#: advtrains/wagons.lua +msgid "!!! Train off track !!!" +msgstr "" + #: advtrains/wagons.lua msgid "(Doors closed)" msgstr "(Türen geschlossen)" +#: advtrains/wagons.lua +msgid "Allow these players to access your wagon:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Clear 'Disable ARS' flag" +msgstr "" + +#: advtrains/wagons.lua +msgid "Current FC: " +msgstr "" + +#: advtrains/wagons.lua +msgid "" +"Destroying wagon with inventory, but inventory is not found? Shouldn't " +"happen!" +msgstr "" + #: advtrains/wagons.lua msgid "Doors are closed! (Try holding sneak key!)" msgstr "Die Türen sind geschlossen." @@ -356,6 +514,10 @@ msgstr "" "Die Türen sind geschlossen. Nutzen Sie Schleichen+Rechtsklick, um trotz " "geschlossener Türen auszusteigen." +#: advtrains/wagons.lua +msgid "Freight Code:" +msgstr "" + #: advtrains/wagons.lua msgid "Get off" msgstr "Aussteigen" @@ -368,10 +530,47 @@ msgstr "Ausstieg zwingen" msgid "Line" msgstr "Linie" +#: advtrains/wagons.lua +msgid "Liquid: " +msgstr "" + +#: advtrains/wagons.lua +msgid "Liquid: empty" +msgstr "" + +#: advtrains/wagons.lua +msgid "Missing train_operator privilege" +msgstr "" + +#: advtrains/wagons.lua +msgid "Next FC:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Not a valid wagon id." +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "Not allowed to do this." +msgstr "Sie dürfen dieses Gleis nicht konfigurieren." + #: advtrains/wagons.lua msgid "Onboard Computer" msgstr "" +#: advtrains/wagons.lua +msgid "Please specify a player name to transfer ownership to." +msgstr "" + +#: advtrains/wagons.lua +msgid "Prev FC" +msgstr "" + +#: advtrains/wagons.lua +msgid "Remote Routesetting" +msgstr "" + #: advtrains/wagons.lua msgid "Routingcode" msgstr "" @@ -396,6 +595,20 @@ msgstr "Innere Anzeige" msgid "Text displayed outside on train" msgstr "Äußere Anzeige" +#: advtrains/wagons.lua +msgid "That player does not exist!" +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "That wagon does not exist!" +msgstr "In diesem Waggon ist kein Sitzplatz vorhanden." + +#: advtrains/wagons.lua +#, fuzzy +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "Das Gleis, auf dem der Waggon platziert werden woll, ist zu kurz." + #: advtrains/wagons.lua msgid "The wagon's inventory is not empty." msgstr "Das Inventar dieses Waggons ist nicht leer." @@ -421,6 +634,26 @@ msgstr "Dieser Waggon gehört @1, Sie dürfen ihn nicht abbauen." msgid "Train ID" msgstr "" +#: advtrains/wagons.lua +msgid "Train overview / coupling control is only shown when the train stands." +msgstr "" + +#: advtrains/wagons.lua +msgid "Train overview /coupling control:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized init=" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized, removing" +msgstr "" + +#: advtrains/wagons.lua +msgid "Wagon @1 ownership changed from @2 to @3" +msgstr "" + #: advtrains/wagons.lua msgid "Wagon needs to be decoupled from other wagons in order to destroy it." msgstr "Der Waggon muss abgekoppelt sein, damit Sie ihn abbauen können." @@ -429,6 +662,10 @@ msgstr "Der Waggon muss abgekoppelt sein, damit Sie ihn abbauen können." msgid "Wagon properties" msgstr "Waggon-Einstellungen" +#: advtrains/wagons.lua +msgid "Wagon road number:" +msgstr "" + #: advtrains/wagons.lua msgid "" "Warning: If you destroy this wagon, you only get some steel back! If you are " @@ -445,6 +682,15 @@ msgstr "Sie haben keinen Zugang zum Führerstand." msgid "You can't get on this wagon." msgstr "Sie können nicht in diesen Waggon einsteigen." +#: advtrains/wagons.lua +#, fuzzy +msgid "You don't have the train_operator privilege." +msgstr "Ihnen fehlt das „@1“-Privileg." + +#: advtrains/wagons.lua +msgid "You have been given ownership of wagon @1" +msgstr "" + #: advtrains_interlocking/routesetting.lua msgid "Route state changed." msgstr "" @@ -469,6 +715,14 @@ msgstr "Sie dürfen ohne das „@1“-Privileg dieses Gleis nicht konfigurieren. msgid "You are not allowed to configure this track." msgstr "Sie dürfen dieses Gleis nicht konfigurieren." +#: advtrains_line_automation/scheduler.lua +msgid "No callback to handle schedule" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Closed" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Dep. Speed" msgstr "Zielgeschwindigkeit bei Abfahrt" @@ -485,10 +739,22 @@ msgstr "Türseite" msgid "Kick out passengers" msgstr "Fahrgäste zum Ausstieg zwingen" +#: advtrains_line_automation/stoprail.lua +msgid "Left" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Next Stop:\n" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Reverse train" msgstr "Zug Umkehren" +#: advtrains_line_automation/stoprail.lua +msgid "Right" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station Code" msgstr "Kennzeichen der Haltestelle" @@ -520,6 +786,18 @@ msgstr "" msgid "Track" msgstr "Gleis" +#: advtrains_line_automation/stoprail.lua +msgid "Trains stopping here (ARS rules)" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Unknown Station" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Wait for signal to clear" +msgstr "" + #: advtrains_luaautomation/active_common.lua msgid "Clear Local Environment" msgstr "" @@ -591,6 +869,39 @@ msgid "" "privilege." msgstr "Sie dürfen ohne das „@1“ keinen passiven LuaATC-Bauteil benennen." +#: advtrains_signals_japan/init.lua +msgid "Caution" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Clear (proceed)" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Danger (halt)" +msgstr "" + +#: advtrains_signals_japan/init.lua +#, fuzzy +msgid "Japanese signal pole" +msgstr "Japanischer Personenzug-Passagierwaggon" + +#: advtrains_signals_japan/init.lua +msgid "Reduced speed" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Restricted speed" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Distant Signal (" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Main Signal (" +msgstr "" + #: advtrains_train_industrial/init.lua msgid "Big Industrial Train Engine" msgstr "Große Industrielle Lokomotive" @@ -742,6 +1053,9 @@ msgstr "Y-Weiche" #~ msgid "This position is protected!" #~ msgstr "Diese Position ist geschützt!" +#~ msgid "This track can not be changed." +#~ msgstr "Dieses Gleis kann nicht geändert werden." + #~ msgid "Use Sneak+rightclick to bypass closed doors!" #~ msgstr "" #~ "Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen " diff --git a/advtrains/po/fr.po b/advtrains/po/fr.po index 3c8f5f6..d773a98 100644 --- a/advtrains/po/fr.po +++ b/advtrains/po/fr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: advtrains\n" "Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" -"POT-Creation-Date: 2024-12-08 15:21+0100\n" -"PO-Revision-Date: 2024-12-04 15:55+0100\n" +"POT-Creation-Date: 2025-03-25 15:40+0100\n" +"PO-Revision-Date: 2025-03-25 15:06+0100\n" "Last-Translator: Tanavit \n" "Language-Team: French\n" "Language: fr\n" @@ -53,7 +53,8 @@ msgstr "Commande (marche)" msgid "Digiline channel" msgstr "Canal Digiline" -#: advtrains/atc.lua advtrains_line_automation/stoprail.lua +#: advtrains/atc.lua advtrains/wagons.lua +#: advtrains_line_automation/stoprail.lua #: advtrains_luaautomation/active_common.lua msgid "Save" msgstr "Sauvegarder" @@ -156,6 +157,141 @@ msgstr "Cabine de pilotage" msgid "Wheel" msgstr "Roue" +#: advtrains/init.lua +msgid " does not exist or is invalid" +msgstr " n'existe pas ou est invalide" + +#: advtrains/init.lua +msgid " is at " +msgstr " est à la position " + +#: advtrains/init.lua +msgid "(log" +msgstr "(log" + +#: advtrains/init.lua +msgid "Advtrains Status: no_action" +msgstr "État d'advtrains : aucune action" + +#: advtrains/init.lua +msgid "Advtrains is already running normally!" +msgstr "Advtrains fonctionne déjà correctement !" + +#: advtrains/init.lua +msgid "" +"Crash during advtrains main step - skipping the shutdown save operation to " +"not save inconsistent data!" +msgstr "" +"Crash durant le pas principal d'advtrains - saut de l'opération de " +"sauvegarde de terminaison pour éviter l'enregistrement de données " +"corrompues !" + +#: advtrains/init.lua +msgid "" +"Data is being saved. While saving, advtrains will remove the players from " +"trains. Save files will be reloaded afterwards!" +msgstr "" +"Données en cours de sauvegarde. Durant cette phase, advtrains débarquera les " +"joueurs des trains. Les fichiers de sauvegarde seront ultérieurement " +"rechargés !" + +# Routage est il le bon terme ? +#: advtrains/init.lua +msgid "Delete all train routes, force them to recalculate" +msgstr "Suppression et recalcul de tous les routages" + +#: advtrains/init.lua +msgid "" +"Detach all players, especially the offline ones, from all trains. Use only " +"when no one serious is on a train." +msgstr "" +"Débarque tous les joueurs, en particulier ceux déconnectés, de tous les " +"trains. À n'utiliser que quand aucun joueur sérieux n'a embarqué." + +#: advtrains/init.lua +msgid "Disable the advtrains globalstep temporarily" +msgstr "Désactive temporairement le pas global d'advtrains" + +#: advtrains/init.lua +msgid "Disabled advtrains successfully" +msgstr "Succès de la désactivation d'advtrains" + +#: advtrains/init.lua +msgid "Instructed to save() but load() was never called!" +msgstr "Appel de save() requis sans appel préalable de load() !" + +#: advtrains/init.lua +msgid "Print advtrains status info" +msgstr "Affiche les informations d'état d'advtrains" + +#: advtrains/init.lua +msgid "Re-enabling advtrains globalstep..." +msgstr "Réacivation du pas global d'advtrains..." + +#: advtrains/init.lua +msgid "Reload successful!" +msgstr "Succès du rechargement !" + +#: advtrains/init.lua +msgid "Removing unused wagon" +msgstr "Suppression d'un wagon inutilisé" + +#: advtrains/init.lua +msgid "Restoring saved state in 1 second..." +msgstr "Restauration du l'état sauvegardé dans une seconde..." + +#: advtrains/init.lua +msgid "Returns the position of the train with the given id" +msgstr "Affiche la position du train identifié" + +#: advtrains/init.lua +msgid "Saving failed: " +msgstr "Échec de sauvegarde : " + +# Routage est il le bon terme ? +#: advtrains/init.lua +msgid "Successfully invalidated train routes" +msgstr "Succès d'invalidation des routages des trains" + +#: advtrains/init.lua +msgid "Teleporting to train " +msgstr "Téléportation au train " + +#: advtrains/init.lua +msgid "Teleports you to the position of the train with the given id" +msgstr "Vous téléporte à la position du train identifié" + +#: advtrains/init.lua +msgid "" +"The advtrains globalstep has been disabled. Trains are not moving, and no " +"data is saved! Run '/at_disable_step no' to enable again!" +msgstr "" +"Le pas global d'advtrains est désactivé. Les trains sont immobiles et aucune " +"donnée n'est sauvegardée. Exécutez '/at_disable_step no ' pour le réactiver !" + +#: advtrains/init.lua +msgid "Train" +msgstr "Identificateur du train" + +#: advtrains/init.lua +msgid "Train " +msgstr "Identificateur du train " + +#: advtrains/init.lua +msgid "from wagon_save table." +msgstr "de la table wagon_save." + +#: advtrains/init.lua +msgid "" +"had no wagons left because of some bug. It is being deleted. Wave it goodbye!" +msgstr "" +"n'a plus de wagon à cause d'un bug quelconque. Il est détruit. Faites lui " +"coucou !" + +#: advtrains/init.lua +msgid "slowdown" +msgstr "ralentissement" + #: advtrains/misc_nodes.lua msgid "@1 Platform (45 degree)" msgstr "Quai @1 (haut, 45°)" @@ -249,21 +385,46 @@ msgstr "Signal mural (droit)" msgid "Wallmounted Signal (top)" msgstr "Signal mural (plafond)" -#: advtrains/trackplacer.lua -msgid "This node can't be changed using the trackworker." -msgstr "Ce nœud ne peut être modifié avec l'outil \"Trackworker\"." +#: advtrains/track_reg_helper.lua +msgid "@1 Slope" +msgstr "Pente @1" + +#: advtrains/track_reg_helper.lua +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "" +"Placement impossible : quantité insuffisante de voie pentue (@1 manquant)" + +#: advtrains/track_reg_helper.lua +msgid "Can't place: There's no slope of length @1" +msgstr "Placement impossible : il n'y a pas de voie pentue de longueur @1" + +#: advtrains/track_reg_helper.lua +msgid "Can't place: no supporting node at upper end." +msgstr "Placement impossible : pas de nœud d'appui à l'extrémité supérieure." + +#: advtrains/track_reg_helper.lua +msgid "Can't place: not pointing at node" +msgstr "Placement impossible : ne pointe pas un nœud" + +#: advtrains/track_reg_helper.lua +msgid "Can't place: space occupied!" +msgstr "Placement impossible : espace occupé !" + +#: advtrains/track_reg_helper.lua advtrains/tracks.lua +msgid "This track can not be removed!" +msgstr "Cette voie ne peut pas être enlevée !" #: advtrains/trackplacer.lua -msgid "This node can't be rotated using the trackworker." -msgstr "Ce nœud ne peut être tourné avec l'outil \"Trackworker\"." +msgid "This node can't be changed using the trackworker!" +msgstr "Ce nœud ne peut être modifié avec l'outil \"Trackworker\" !" #: advtrains/trackplacer.lua -msgid "This track can not be changed." -msgstr "Cette voie ne peut pas être modifiée." +msgid "This node can't be rotated using the trackworker!" +msgstr "Ce nœud ne peut être tourné avec l'outil \"Trackworker\" !" #: advtrains/trackplacer.lua -msgid "This track can not be rotated." -msgstr "Cette voie ne peut pas être tournée." +msgid "This track can not be rotated!" +msgstr "Cette voie ne peut pas être tournée !" #: advtrains/trackplacer.lua msgid "" @@ -278,31 +439,6 @@ msgstr "" "\n" "Clic-Droit : tourne l'objet" -#: advtrains/tracks.lua -msgid "@1 Slope" -msgstr "Pente @1" - -#: advtrains/tracks.lua -msgid "Can't place slope: Not enough slope items left (@1 required)." -msgstr "" -"Placement impossible : quantité insuffisante de voie pentue (@1 manquant)." - -#: advtrains/tracks.lua -msgid "Can't place slope: There's no slope of length @1." -msgstr "Placement impossible : il n'y a pas de voie pentue de longueur @1." - -#: advtrains/tracks.lua -msgid "Can't place slope: no supporting node at upper end." -msgstr "Placement impossible : pas de nœud d'appui à l'extrémité supérieure." - -#: advtrains/tracks.lua -msgid "Can't place slope: not pointing at node." -msgstr "Placement impossible : ne pointe pas un nœud." - -#: advtrains/tracks.lua -msgid "Can't place slope: space occupied." -msgstr "Placement impossible : espace occupé." - #: advtrains/tracks.lua msgid "Position is occupied by a train." msgstr "Cet emplacement est occupé par un train." @@ -315,10 +451,6 @@ msgstr "Il y a un \"Signal Influence Point\" ici." msgid "There's a Track Circuit Break here." msgstr "Il y a un \"Track Circuit Break\" ici." -#: advtrains/tracks.lua -msgid "This track can not be removed." -msgstr "Cette voie ne peut pas être enlevée." - #: advtrains/trainhud.lua msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." msgstr "" @@ -341,10 +473,40 @@ msgstr "" "Outil de propriété du wagon\n" "Frappez un wagon pour voir et modifier ses propriétés" +#: advtrains/wagons.lua +msgid " units" +msgstr " Unités" + +#: advtrains/wagons.lua +msgid " wagon:destroy(): data is not set!" +msgstr " Appel de wagon:destroy() : données non définies !" + +#: advtrains/wagons.lua +msgid "!!! Train off track !!!" +msgstr "!!! Train hors voie !!!" + #: advtrains/wagons.lua msgid "(Doors closed)" msgstr "(Portes closes)" +#: advtrains/wagons.lua +msgid "Allow these players to access your wagon:" +msgstr "Autoriser ces joueurs à embarquer :" + +#: advtrains/wagons.lua +msgid "Clear 'Disable ARS' flag" +msgstr "Effacer le drapeau \"Désactiver l'ARS\"" + +#: advtrains/wagons.lua +msgid "Current FC: " +msgstr "Code de fret courant: " + +#: advtrains/wagons.lua +msgid "" +"Destroying wagon with inventory, but inventory is not found? Shouldn't " +"happen!" +msgstr "Desctruction d'un wagon avec inventaire introuvable ? Anomalie !" + #: advtrains/wagons.lua msgid "Doors are closed! (Try holding sneak key!)" msgstr "Portes closes : (Essayez la \"sneak key\"!\")" @@ -357,6 +519,10 @@ msgstr "" "Portes closes ! Utilisez \"Marcher lentement (Sneak)\" et Clic-Droit pour " "franchir les portes et débarquer." +#: advtrains/wagons.lua +msgid "Freight Code:" +msgstr "Code de frêt :" + #: advtrains/wagons.lua msgid "Get off" msgstr "Débarquer" @@ -369,10 +535,47 @@ msgstr "Débarquer (de force)" msgid "Line" msgstr "Ligne" +#: advtrains/wagons.lua +msgid "Liquid: " +msgstr "Liquide : " + +#: advtrains/wagons.lua +msgid "Liquid: empty" +msgstr "Liquide : vide" + +#: advtrains/wagons.lua +msgid "Missing train_operator privilege" +msgstr "Privilège \"train_operator\" manquant" + +#: advtrains/wagons.lua +msgid "Next FC:" +msgstr "Code de fret suivant :" + +#: advtrains/wagons.lua +msgid "Not a valid wagon id." +msgstr "Identificateur de wagon invalide." + +#: advtrains/wagons.lua +msgid "Not allowed to do this." +msgstr "Vous n'êtes pas autorisé effectuer ceci." + #: advtrains/wagons.lua msgid "Onboard Computer" msgstr "Ordinateur embarqué" +#: advtrains/wagons.lua +msgid "Please specify a player name to transfer ownership to." +msgstr "" +"Spécifiez le nom du joueur à qui la propriété doit être transférée, SVP." + +#: advtrains/wagons.lua +msgid "Prev FC" +msgstr "Code de fret précédent" + +#: advtrains/wagons.lua +msgid "Remote Routesetting" +msgstr "Routage à distance" + #: advtrains/wagons.lua msgid "Routingcode" msgstr "Code de routage" @@ -397,6 +600,18 @@ msgstr "Texte affiché à l'intérieur du train" msgid "Text displayed outside on train" msgstr "Texte affiché à l'extérieur du train" +#: advtrains/wagons.lua +msgid "That player does not exist!" +msgstr "Ce joueur n'existe pas !" + +#: advtrains/wagons.lua +msgid "That wagon does not exist!" +msgstr "Ce wagon n'a pas de siège !" + +#: advtrains/wagons.lua +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "La voie sur laquelle vous tentez de placer le wagon est trop courte !" + #: advtrains/wagons.lua msgid "The wagon's inventory is not empty." msgstr "Le stock de ce wagon n'est pas vide." @@ -421,6 +636,28 @@ msgstr "Ce wagon est la propriété de @1, vous ne pouvez pas le détruire." msgid "Train ID" msgstr "Identificateur du train" +#: advtrains/wagons.lua +msgid "Train overview / coupling control is only shown when the train stands." +msgstr "" +"Aperçu du train / commande d'accouplement montré uniquement à l'arrêt du " +"train." + +#: advtrains/wagons.lua +msgid "Train overview /coupling control:" +msgstr "Aperçu du train / commande d'accouplement :" + +#: advtrains/wagons.lua +msgid "Uninitialized init=" +msgstr "Variable init non initialisée" + +#: advtrains/wagons.lua +msgid "Uninitialized, removing" +msgstr "Non initialisé, retiré" + +#: advtrains/wagons.lua +msgid "Wagon @1 ownership changed from @2 to @3" +msgstr "La propriété du wagon @1 a été transférée de @2 à @3" + #: advtrains/wagons.lua msgid "Wagon needs to be decoupled from other wagons in order to destroy it." msgstr "" @@ -430,6 +667,10 @@ msgstr "" msgid "Wagon properties" msgstr "Propriétés du wagon" +#: advtrains/wagons.lua +msgid "Wagon road number:" +msgstr "Immatriculation du wagon :" + #: advtrains/wagons.lua msgid "" "Warning: If you destroy this wagon, you only get some steel back! If you are " @@ -447,9 +688,17 @@ msgstr "Accès interdit au poste de pilotage." msgid "You can't get on this wagon." msgstr "Montée impossible dans ce wagon." +#: advtrains/wagons.lua +msgid "You don't have the train_operator privilege." +msgstr "Vous ne possédez pas le privilège \"train_operator\"." + +#: advtrains/wagons.lua +msgid "You have been given ownership of wagon @1" +msgstr "La propriété du wagon @1 vous a été transférée" + #: advtrains_interlocking/routesetting.lua msgid "Route state changed." -msgstr "" +msgstr "Changement d'état de l'itinéraire." #: advtrains_interlocking/tsr_rail.lua msgid "Point Speed Restriction Track" @@ -471,9 +720,17 @@ msgstr "Vous n'êtes pas autorisé à configurer cette voie sans le privilège @ msgid "You are not allowed to configure this track." msgstr "Vous n'êtes pas autorisé à configurer cette voie." +#: advtrains_line_automation/scheduler.lua +msgid "No callback to handle schedule" +msgstr "Absence de fonction de gestion de planning" + +#: advtrains_line_automation/stoprail.lua +msgid "Closed" +msgstr "Fermé" + #: advtrains_line_automation/stoprail.lua msgid "Dep. Speed" -msgstr "Vitesse de départ" +msgstr "Vit. de départ" #: advtrains_line_automation/stoprail.lua msgid "Door Delay" @@ -481,16 +738,28 @@ msgstr "Durée d'ouverture des portes" #: advtrains_line_automation/stoprail.lua msgid "Door Side" -msgstr "Coté d'ouvertures des portes" +msgstr "Ouv. des portes coté" #: advtrains_line_automation/stoprail.lua msgid "Kick out passengers" msgstr "Éjecter les passagers" +#: advtrains_line_automation/stoprail.lua +msgid "Left" +msgstr "Gauche" + +#: advtrains_line_automation/stoprail.lua +msgid "Next Stop:\n" +msgstr "Prochain arrêt :\n" + #: advtrains_line_automation/stoprail.lua msgid "Reverse train" msgstr "Inversion du sens de marche" +#: advtrains_line_automation/stoprail.lua +msgid "Right" +msgstr "Droit" + #: advtrains_line_automation/stoprail.lua msgid "Station Code" msgstr "Code de Station" @@ -521,6 +790,18 @@ msgstr "" msgid "Track" msgstr "Voie" +#: advtrains_line_automation/stoprail.lua +msgid "Trains stopping here (ARS rules)" +msgstr "Trains marquant l'arrêt (règles ARS)" + +#: advtrains_line_automation/stoprail.lua +msgid "Unknown Station" +msgstr "Gare inconnue" + +#: advtrains_line_automation/stoprail.lua +msgid "Wait for signal to clear" +msgstr "En attente de signal d'autorisation" + #: advtrains_luaautomation/active_common.lua msgid "Clear Local Environment" msgstr "Effacer l'environnement LuaATC" @@ -591,6 +872,38 @@ msgid "" "privilege." msgstr "Vous ne pouvez nommer un composant LuaATC passif sans le privilege @1." +#: advtrains_signals_japan/init.lua +msgid "Caution" +msgstr "Attention" + +#: advtrains_signals_japan/init.lua +msgid "Clear (proceed)" +msgstr "Autorisation (procédez)" + +#: advtrains_signals_japan/init.lua +msgid "Danger (halt)" +msgstr "Danger (stop)" + +#: advtrains_signals_japan/init.lua +msgid "Japanese signal pole" +msgstr "Voiture Japonaise" + +#: advtrains_signals_japan/init.lua +msgid "Reduced speed" +msgstr "Vitesse réduite" + +#: advtrains_signals_japan/init.lua +msgid "Restricted speed" +msgstr "Vitesse limitée" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Distant Signal (" +msgstr "Signal distant métro de Munich (" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Main Signal (" +msgstr "Signal principal métro de Munich (" + #: advtrains_train_industrial/init.lua msgid "Big Industrial Train Engine" msgstr "Grosse locomotive industrielle" @@ -701,6 +1014,9 @@ msgstr "Voie de Déchargement" msgid "Y-turnout" msgstr "Embranchement en Y" +#~ msgid ", using placeholder" +#~ msgstr ", dans un espace réservé" + #~ msgid "" #~ "ATC controller, mode @1\n" #~ "Channel: @2" @@ -727,6 +1043,9 @@ msgstr "Embranchement en Y" #~ msgid "Deprecated Track" #~ msgstr "Voie déconseillée" +#~ msgid "Left,Right,Closed;" +#~ msgstr "Gauche,Droit,Fermé;" + #~ msgid "Lock couples" #~ msgstr "Verrouiller l'accouplement" @@ -743,6 +1062,12 @@ msgstr "Embranchement en Y" #~ msgid "This position is protected!" #~ msgstr "Cet emplacement est protégé !" +#~ msgid "This track can not be changed." +#~ msgstr "Cette voie ne peut pas être modifiée." + +#~ msgid "Unable to load wagon type" +#~ msgstr "Impossible de charger le type du wagon" + #~ msgid "Use Sneak+rightclick to bypass closed doors!" #~ msgstr "" #~ "Utilisez \"Marcher lentement (Sneak)\" et Clic-Droit pour franchir les " diff --git a/advtrains/po/update-translations.sh b/advtrains/po/update-translations.sh index 1b919d9..4c22c85 100755 --- a/advtrains/po/update-translations.sh +++ b/advtrains/po/update-translations.sh @@ -7,7 +7,6 @@ BTDIR="$ATDIR/../basic_trains" POTFILE="$PODIR/advtrains.pot" xgettext \ - -v -v -v \ -D "$ATDIR" \ -D "$BTDIR" \ -d advtrains \ diff --git a/advtrains/po/zh_CN.po b/advtrains/po/zh_CN.po index 1dbf08f..f1a3c0f 100644 --- a/advtrains/po/zh_CN.po +++ b/advtrains/po/zh_CN.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: advtrains\n" "Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" -"POT-Creation-Date: 2024-12-08 15:21+0100\n" +"POT-Creation-Date: 2025-03-25 15:40+0100\n" "PO-Revision-Date: 2023-10-09 11:24+0200\n" "Last-Translator: Y. Wang \n" "Language-Team: Chinese (Simplified)\n" @@ -53,7 +53,8 @@ msgstr "命令 (激活时)" msgid "Digiline channel" msgstr "Digiline 频道" -#: advtrains/atc.lua advtrains_line_automation/stoprail.lua +#: advtrains/atc.lua advtrains/wagons.lua +#: advtrains_line_automation/stoprail.lua #: advtrains_luaautomation/active_common.lua msgid "Save" msgstr "保存" @@ -151,6 +152,128 @@ msgstr "驾驶室" msgid "Wheel" msgstr "车轮" +#: advtrains/init.lua +msgid " does not exist or is invalid" +msgstr "" + +#: advtrains/init.lua +msgid " is at " +msgstr "" + +#: advtrains/init.lua +msgid "(log" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains Status: no_action" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains is already running normally!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Crash during advtrains main step - skipping the shutdown save operation to " +"not save inconsistent data!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Data is being saved. While saving, advtrains will remove the players from " +"trains. Save files will be reloaded afterwards!" +msgstr "" + +#: advtrains/init.lua +msgid "Delete all train routes, force them to recalculate" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Detach all players, especially the offline ones, from all trains. Use only " +"when no one serious is on a train." +msgstr "" + +#: advtrains/init.lua +msgid "Disable the advtrains globalstep temporarily" +msgstr "" + +#: advtrains/init.lua +msgid "Disabled advtrains successfully" +msgstr "" + +#: advtrains/init.lua +msgid "Instructed to save() but load() was never called!" +msgstr "" + +#: advtrains/init.lua +msgid "Print advtrains status info" +msgstr "" + +#: advtrains/init.lua +msgid "Re-enabling advtrains globalstep..." +msgstr "" + +#: advtrains/init.lua +msgid "Reload successful!" +msgstr "" + +#: advtrains/init.lua +msgid "Removing unused wagon" +msgstr "" + +#: advtrains/init.lua +msgid "Restoring saved state in 1 second..." +msgstr "" + +#: advtrains/init.lua +msgid "Returns the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "Saving failed: " +msgstr "" + +#: advtrains/init.lua +msgid "Successfully invalidated train routes" +msgstr "" + +#: advtrains/init.lua +msgid "Teleporting to train " +msgstr "" + +#: advtrains/init.lua +msgid "Teleports you to the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "" +"The advtrains globalstep has been disabled. Trains are not moving, and no " +"data is saved! Run '/at_disable_step no' to enable again!" +msgstr "" + +#: advtrains/init.lua +msgid "Train" +msgstr "" + +#: advtrains/init.lua +#, fuzzy +msgid "Train " +msgstr "已复制列车。" + +#: advtrains/init.lua +msgid "from wagon_save table." +msgstr "" + +#: advtrains/init.lua +msgid "" +"had no wagons left because of some bug. It is being deleted. Wave it goodbye!" +msgstr "" + +#: advtrains/init.lua +msgid "slowdown" +msgstr "" + #: advtrains/misc_nodes.lua msgid "@1 Platform (45 degree)" msgstr "较高的@1站台 (45°)" @@ -233,20 +356,53 @@ msgstr "壁挂式信号灯 (右侧)" msgid "Wallmounted Signal (top)" msgstr "悬挂式信号灯" +#: advtrains/track_reg_helper.lua +msgid "@1 Slope" +msgstr "@1斜坡" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "无法放置斜坡:您没有足够的铁路斜坡放置工具 (您总共需要@1个)" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: There's no slope of length @1" +msgstr "无法放置斜坡:advtrains 不支持长度为@1米的斜坡。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: no supporting node at upper end." +msgstr "无法放置斜坡:较高端没有支撑方块。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: not pointing at node" +msgstr "无法放置斜坡:您没有选择任何方块。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: space occupied!" +msgstr "无法放置斜坡:此区域已被占用。" + +#: advtrains/track_reg_helper.lua advtrains/tracks.lua +#, fuzzy +msgid "This track can not be removed!" +msgstr "您不能移除这段轨道。" + #: advtrains/trackplacer.lua -msgid "This node can't be changed using the trackworker." +#, fuzzy +msgid "This node can't be changed using the trackworker!" msgstr "您不能使用铁路调整工具调整这个方块。" #: advtrains/trackplacer.lua -msgid "This node can't be rotated using the trackworker." +#, fuzzy +msgid "This node can't be rotated using the trackworker!" msgstr "您不能使用铁路调整工具旋转这个方块。" #: advtrains/trackplacer.lua -msgid "This track can not be changed." -msgstr "您不能调整这段轨道。" - -#: advtrains/trackplacer.lua -msgid "This track can not be rotated." +#, fuzzy +msgid "This track can not be rotated!" msgstr "您不能旋转这段轨道。" #: advtrains/trackplacer.lua @@ -261,30 +417,6 @@ msgstr "" "左键单击:切换轨道类型\n" "右键单击:旋转方块" -#: advtrains/tracks.lua -msgid "@1 Slope" -msgstr "@1斜坡" - -#: advtrains/tracks.lua -msgid "Can't place slope: Not enough slope items left (@1 required)." -msgstr "无法放置斜坡:您没有足够的铁路斜坡放置工具 (您总共需要@1个)" - -#: advtrains/tracks.lua -msgid "Can't place slope: There's no slope of length @1." -msgstr "无法放置斜坡:advtrains 不支持长度为@1米的斜坡。" - -#: advtrains/tracks.lua -msgid "Can't place slope: no supporting node at upper end." -msgstr "无法放置斜坡:较高端没有支撑方块。" - -#: advtrains/tracks.lua -msgid "Can't place slope: not pointing at node." -msgstr "无法放置斜坡:您没有选择任何方块。" - -#: advtrains/tracks.lua -msgid "Can't place slope: space occupied." -msgstr "无法放置斜坡:此区域已被占用。" - #: advtrains/tracks.lua msgid "Position is occupied by a train." msgstr "" @@ -297,10 +429,6 @@ msgstr "" msgid "There's a Track Circuit Break here." msgstr "" -#: advtrains/tracks.lua -msgid "This track can not be removed." -msgstr "您不能移除这段轨道。" - #: advtrains/trainhud.lua msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." msgstr "" @@ -320,10 +448,40 @@ msgid "" "Punch a wagon to view and edit the Wagon Properties" msgstr "" +#: advtrains/wagons.lua +msgid " units" +msgstr "" + +#: advtrains/wagons.lua +msgid " wagon:destroy(): data is not set!" +msgstr "" + +#: advtrains/wagons.lua +msgid "!!! Train off track !!!" +msgstr "" + #: advtrains/wagons.lua msgid "(Doors closed)" msgstr "(车门已关闭)" +#: advtrains/wagons.lua +msgid "Allow these players to access your wagon:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Clear 'Disable ARS' flag" +msgstr "" + +#: advtrains/wagons.lua +msgid "Current FC: " +msgstr "" + +#: advtrains/wagons.lua +msgid "" +"Destroying wagon with inventory, but inventory is not found? Shouldn't " +"happen!" +msgstr "" + #: advtrains/wagons.lua msgid "Doors are closed! (Try holding sneak key!)" msgstr "" @@ -334,6 +492,10 @@ msgid "" "off." msgstr "车门已关闭,请使用潜行+右键单击下车。" +#: advtrains/wagons.lua +msgid "Freight Code:" +msgstr "" + #: advtrains/wagons.lua msgid "Get off" msgstr "下车" @@ -346,10 +508,47 @@ msgstr "强制下车" msgid "Line" msgstr "火车线路" +#: advtrains/wagons.lua +msgid "Liquid: " +msgstr "" + +#: advtrains/wagons.lua +msgid "Liquid: empty" +msgstr "" + +#: advtrains/wagons.lua +msgid "Missing train_operator privilege" +msgstr "" + +#: advtrains/wagons.lua +msgid "Next FC:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Not a valid wagon id." +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "Not allowed to do this." +msgstr "您不能调整这段轨道。" + #: advtrains/wagons.lua msgid "Onboard Computer" msgstr "" +#: advtrains/wagons.lua +msgid "Please specify a player name to transfer ownership to." +msgstr "" + +#: advtrains/wagons.lua +msgid "Prev FC" +msgstr "" + +#: advtrains/wagons.lua +msgid "Remote Routesetting" +msgstr "" + #: advtrains/wagons.lua msgid "Routingcode" msgstr "路由码" @@ -374,6 +573,20 @@ msgstr "车厢内部显示" msgid "Text displayed outside on train" msgstr "车厢外部显示" +#: advtrains/wagons.lua +msgid "That player does not exist!" +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "That wagon does not exist!" +msgstr "这节车厢没有座位。" + +#: advtrains/wagons.lua +#, fuzzy +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "轨道太短。" + #: advtrains/wagons.lua msgid "The wagon's inventory is not empty." msgstr "" @@ -399,6 +612,26 @@ msgstr "这是 @1 的车厢,您不能摧毁它。" msgid "Train ID" msgstr "" +#: advtrains/wagons.lua +msgid "Train overview / coupling control is only shown when the train stands." +msgstr "" + +#: advtrains/wagons.lua +msgid "Train overview /coupling control:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized init=" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized, removing" +msgstr "" + +#: advtrains/wagons.lua +msgid "Wagon @1 ownership changed from @2 to @3" +msgstr "" + #: advtrains/wagons.lua msgid "Wagon needs to be decoupled from other wagons in order to destroy it." msgstr "" @@ -407,6 +640,10 @@ msgstr "" msgid "Wagon properties" msgstr "车厢属性" +#: advtrains/wagons.lua +msgid "Wagon road number:" +msgstr "" + #: advtrains/wagons.lua msgid "" "Warning: If you destroy this wagon, you only get some steel back! If you are " @@ -423,6 +660,15 @@ msgstr "" msgid "You can't get on this wagon." msgstr "" +#: advtrains/wagons.lua +#, fuzzy +msgid "You don't have the train_operator privilege." +msgstr "您没有“@1”权限。" + +#: advtrains/wagons.lua +msgid "You have been given ownership of wagon @1" +msgstr "" + #: advtrains_interlocking/routesetting.lua msgid "Route state changed." msgstr "" @@ -447,6 +693,14 @@ msgstr "您没有“@1”权限,不能调整这段轨道。" msgid "You are not allowed to configure this track." msgstr "您不能调整这段轨道。" +#: advtrains_line_automation/scheduler.lua +msgid "No callback to handle schedule" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Closed" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Dep. Speed" msgstr "出发速度" @@ -463,10 +717,22 @@ msgstr "" msgid "Kick out passengers" msgstr "踢出乘客" +#: advtrains_line_automation/stoprail.lua +msgid "Left" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Next Stop:\n" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Reverse train" msgstr "改变行车方向" +#: advtrains_line_automation/stoprail.lua +msgid "Right" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station Code" msgstr "车站代码" @@ -495,6 +761,18 @@ msgstr "" msgid "Track" msgstr "轨道" +#: advtrains_line_automation/stoprail.lua +msgid "Trains stopping here (ARS rules)" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Unknown Station" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Wait for signal to clear" +msgstr "" + #: advtrains_luaautomation/active_common.lua msgid "Clear Local Environment" msgstr "" @@ -563,6 +841,39 @@ msgid "" "privilege." msgstr "您没有“@1”权限,不能命名被动元件。" +#: advtrains_signals_japan/init.lua +msgid "Caution" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Clear (proceed)" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Danger (halt)" +msgstr "" + +#: advtrains_signals_japan/init.lua +#, fuzzy +msgid "Japanese signal pole" +msgstr "高速列车车厢" + +#: advtrains_signals_japan/init.lua +msgid "Reduced speed" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Restricted speed" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Distant Signal (" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Main Signal (" +msgstr "" + #: advtrains_train_industrial/init.lua msgid "Big Industrial Train Engine" msgstr "大型工业用火车头" @@ -717,6 +1028,9 @@ msgstr "对称道岔" #~ msgid "This position is protected!" #~ msgstr "这里已被保护。" +#~ msgid "This track can not be changed." +#~ msgstr "您不能调整这段轨道。" + #~ msgid "Use Sneak+rightclick to bypass closed doors!" #~ msgstr "请使用潜行+右键上车。" diff --git a/advtrains/po/zh_TW.po b/advtrains/po/zh_TW.po index 56b6531..ec65737 100644 --- a/advtrains/po/zh_TW.po +++ b/advtrains/po/zh_TW.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: advtrains\n" "Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n" -"POT-Creation-Date: 2024-12-08 15:21+0100\n" +"POT-Creation-Date: 2025-03-25 15:40+0100\n" "PO-Revision-Date: 2023-10-09 11:31+0200\n" "Last-Translator: Y. Wang \n" "Language-Team: Chinese (Traditional)\n" @@ -53,7 +53,8 @@ msgstr "命令 (啟用時)" msgid "Digiline channel" msgstr "Digiline 頻道" -#: advtrains/atc.lua advtrains_line_automation/stoprail.lua +#: advtrains/atc.lua advtrains/wagons.lua +#: advtrains_line_automation/stoprail.lua #: advtrains_luaautomation/active_common.lua msgid "Save" msgstr "儲存" @@ -151,6 +152,128 @@ msgstr "駕駛室" msgid "Wheel" msgstr "車輪" +#: advtrains/init.lua +msgid " does not exist or is invalid" +msgstr "" + +#: advtrains/init.lua +msgid " is at " +msgstr "" + +#: advtrains/init.lua +msgid "(log" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains Status: no_action" +msgstr "" + +#: advtrains/init.lua +msgid "Advtrains is already running normally!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Crash during advtrains main step - skipping the shutdown save operation to " +"not save inconsistent data!" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Data is being saved. While saving, advtrains will remove the players from " +"trains. Save files will be reloaded afterwards!" +msgstr "" + +#: advtrains/init.lua +msgid "Delete all train routes, force them to recalculate" +msgstr "" + +#: advtrains/init.lua +msgid "" +"Detach all players, especially the offline ones, from all trains. Use only " +"when no one serious is on a train." +msgstr "" + +#: advtrains/init.lua +msgid "Disable the advtrains globalstep temporarily" +msgstr "" + +#: advtrains/init.lua +msgid "Disabled advtrains successfully" +msgstr "" + +#: advtrains/init.lua +msgid "Instructed to save() but load() was never called!" +msgstr "" + +#: advtrains/init.lua +msgid "Print advtrains status info" +msgstr "" + +#: advtrains/init.lua +msgid "Re-enabling advtrains globalstep..." +msgstr "" + +#: advtrains/init.lua +msgid "Reload successful!" +msgstr "" + +#: advtrains/init.lua +msgid "Removing unused wagon" +msgstr "" + +#: advtrains/init.lua +msgid "Restoring saved state in 1 second..." +msgstr "" + +#: advtrains/init.lua +msgid "Returns the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "Saving failed: " +msgstr "" + +#: advtrains/init.lua +msgid "Successfully invalidated train routes" +msgstr "" + +#: advtrains/init.lua +msgid "Teleporting to train " +msgstr "" + +#: advtrains/init.lua +msgid "Teleports you to the position of the train with the given id" +msgstr "" + +#: advtrains/init.lua +msgid "" +"The advtrains globalstep has been disabled. Trains are not moving, and no " +"data is saved! Run '/at_disable_step no' to enable again!" +msgstr "" + +#: advtrains/init.lua +msgid "Train" +msgstr "" + +#: advtrains/init.lua +#, fuzzy +msgid "Train " +msgstr "已複製火車。" + +#: advtrains/init.lua +msgid "from wagon_save table." +msgstr "" + +#: advtrains/init.lua +msgid "" +"had no wagons left because of some bug. It is being deleted. Wave it goodbye!" +msgstr "" + +#: advtrains/init.lua +msgid "slowdown" +msgstr "" + #: advtrains/misc_nodes.lua msgid "@1 Platform (45 degree)" msgstr "較高的@1月臺 (45°)" @@ -233,20 +356,53 @@ msgstr "壁掛式色燈號誌機 (右側)" msgid "Wallmounted Signal (top)" msgstr "懸掛式色燈號誌機" +#: advtrains/track_reg_helper.lua +msgid "@1 Slope" +msgstr "@1斜坡" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: Not enough slope items left (@1 required)" +msgstr "無法放置斜坡:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個)" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: There's no slope of length @1" +msgstr "無法放置斜坡:advtrains 不支援長度為@1米的斜坡。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: no supporting node at upper end." +msgstr "無法放置斜坡:較高階沒有支撐方塊。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: not pointing at node" +msgstr "無法放置斜坡:您沒有選擇任何方塊。" + +#: advtrains/track_reg_helper.lua +#, fuzzy +msgid "Can't place: space occupied!" +msgstr "無法放置斜坡:此區域已被佔用。" + +#: advtrains/track_reg_helper.lua advtrains/tracks.lua +#, fuzzy +msgid "This track can not be removed!" +msgstr "您不能移除這段軌道。" + #: advtrains/trackplacer.lua -msgid "This node can't be changed using the trackworker." +#, fuzzy +msgid "This node can't be changed using the trackworker!" msgstr "您不能使用鐵路調整工具調整這個方塊。" #: advtrains/trackplacer.lua -msgid "This node can't be rotated using the trackworker." +#, fuzzy +msgid "This node can't be rotated using the trackworker!" msgstr "您不能使用鐵路調整工具旋轉這個方塊。" #: advtrains/trackplacer.lua -msgid "This track can not be changed." -msgstr "您不能調整這段軌道。" - -#: advtrains/trackplacer.lua -msgid "This track can not be rotated." +#, fuzzy +msgid "This track can not be rotated!" msgstr "您不能旋轉這段軌道。" #: advtrains/trackplacer.lua @@ -261,30 +417,6 @@ msgstr "" "左鍵單擊:切換軌道型別\n" "右鍵單擊:旋轉方塊" -#: advtrains/tracks.lua -msgid "@1 Slope" -msgstr "@1斜坡" - -#: advtrains/tracks.lua -msgid "Can't place slope: Not enough slope items left (@1 required)." -msgstr "無法放置斜坡:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個)" - -#: advtrains/tracks.lua -msgid "Can't place slope: There's no slope of length @1." -msgstr "無法放置斜坡:advtrains 不支援長度為@1米的斜坡。" - -#: advtrains/tracks.lua -msgid "Can't place slope: no supporting node at upper end." -msgstr "無法放置斜坡:較高階沒有支撐方塊。" - -#: advtrains/tracks.lua -msgid "Can't place slope: not pointing at node." -msgstr "無法放置斜坡:您沒有選擇任何方塊。" - -#: advtrains/tracks.lua -msgid "Can't place slope: space occupied." -msgstr "無法放置斜坡:此區域已被佔用。" - #: advtrains/tracks.lua msgid "Position is occupied by a train." msgstr "" @@ -297,10 +429,6 @@ msgstr "" msgid "There's a Track Circuit Break here." msgstr "" -#: advtrains/tracks.lua -msgid "This track can not be removed." -msgstr "您不能移除這段軌道。" - #: advtrains/trainhud.lua msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again." msgstr "" @@ -320,10 +448,40 @@ msgid "" "Punch a wagon to view and edit the Wagon Properties" msgstr "" +#: advtrains/wagons.lua +msgid " units" +msgstr "" + +#: advtrains/wagons.lua +msgid " wagon:destroy(): data is not set!" +msgstr "" + +#: advtrains/wagons.lua +msgid "!!! Train off track !!!" +msgstr "" + #: advtrains/wagons.lua msgid "(Doors closed)" msgstr "(車門已關閉)" +#: advtrains/wagons.lua +msgid "Allow these players to access your wagon:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Clear 'Disable ARS' flag" +msgstr "" + +#: advtrains/wagons.lua +msgid "Current FC: " +msgstr "" + +#: advtrains/wagons.lua +msgid "" +"Destroying wagon with inventory, but inventory is not found? Shouldn't " +"happen!" +msgstr "" + #: advtrains/wagons.lua msgid "Doors are closed! (Try holding sneak key!)" msgstr "" @@ -334,6 +492,10 @@ msgid "" "off." msgstr "車門已關閉,請使用潛行+右鍵單擊下車。" +#: advtrains/wagons.lua +msgid "Freight Code:" +msgstr "" + #: advtrains/wagons.lua msgid "Get off" msgstr "下車" @@ -346,10 +508,47 @@ msgstr "強制下車" msgid "Line" msgstr "火車線路" +#: advtrains/wagons.lua +msgid "Liquid: " +msgstr "" + +#: advtrains/wagons.lua +msgid "Liquid: empty" +msgstr "" + +#: advtrains/wagons.lua +msgid "Missing train_operator privilege" +msgstr "" + +#: advtrains/wagons.lua +msgid "Next FC:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Not a valid wagon id." +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "Not allowed to do this." +msgstr "您不能調整這段軌道。" + #: advtrains/wagons.lua msgid "Onboard Computer" msgstr "" +#: advtrains/wagons.lua +msgid "Please specify a player name to transfer ownership to." +msgstr "" + +#: advtrains/wagons.lua +msgid "Prev FC" +msgstr "" + +#: advtrains/wagons.lua +msgid "Remote Routesetting" +msgstr "" + #: advtrains/wagons.lua msgid "Routingcode" msgstr "路由碼" @@ -374,6 +573,20 @@ msgstr "車廂內部顯示" msgid "Text displayed outside on train" msgstr "車廂外部顯示" +#: advtrains/wagons.lua +msgid "That player does not exist!" +msgstr "" + +#: advtrains/wagons.lua +#, fuzzy +msgid "That wagon does not exist!" +msgstr "這節車廂沒有座位。" + +#: advtrains/wagons.lua +#, fuzzy +msgid "The track you are trying to place the wagon on is not long enough!" +msgstr "軌道太短。" + #: advtrains/wagons.lua msgid "The wagon's inventory is not empty." msgstr "" @@ -399,6 +612,26 @@ msgstr "這是 @1 的車廂,您不能摧毀它。" msgid "Train ID" msgstr "" +#: advtrains/wagons.lua +msgid "Train overview / coupling control is only shown when the train stands." +msgstr "" + +#: advtrains/wagons.lua +msgid "Train overview /coupling control:" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized init=" +msgstr "" + +#: advtrains/wagons.lua +msgid "Uninitialized, removing" +msgstr "" + +#: advtrains/wagons.lua +msgid "Wagon @1 ownership changed from @2 to @3" +msgstr "" + #: advtrains/wagons.lua msgid "Wagon needs to be decoupled from other wagons in order to destroy it." msgstr "" @@ -407,6 +640,10 @@ msgstr "" msgid "Wagon properties" msgstr "車廂屬性" +#: advtrains/wagons.lua +msgid "Wagon road number:" +msgstr "" + #: advtrains/wagons.lua msgid "" "Warning: If you destroy this wagon, you only get some steel back! If you are " @@ -423,6 +660,15 @@ msgstr "" msgid "You can't get on this wagon." msgstr "" +#: advtrains/wagons.lua +#, fuzzy +msgid "You don't have the train_operator privilege." +msgstr "您沒有「@1」許可權。" + +#: advtrains/wagons.lua +msgid "You have been given ownership of wagon @1" +msgstr "" + #: advtrains_interlocking/routesetting.lua msgid "Route state changed." msgstr "" @@ -447,6 +693,14 @@ msgstr "您沒有「@1」許可權,不能調整這段軌道。" msgid "You are not allowed to configure this track." msgstr "您不能調整這段軌道。" +#: advtrains_line_automation/scheduler.lua +msgid "No callback to handle schedule" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Closed" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Dep. Speed" msgstr "出發速度" @@ -463,10 +717,22 @@ msgstr "" msgid "Kick out passengers" msgstr "踢出乘客" +#: advtrains_line_automation/stoprail.lua +msgid "Left" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Next Stop:\n" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Reverse train" msgstr "改變行車方向" +#: advtrains_line_automation/stoprail.lua +msgid "Right" +msgstr "" + #: advtrains_line_automation/stoprail.lua msgid "Station Code" msgstr "車站碼" @@ -495,6 +761,18 @@ msgstr "" msgid "Track" msgstr "軌道" +#: advtrains_line_automation/stoprail.lua +msgid "Trains stopping here (ARS rules)" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Unknown Station" +msgstr "" + +#: advtrains_line_automation/stoprail.lua +msgid "Wait for signal to clear" +msgstr "" + #: advtrains_luaautomation/active_common.lua msgid "Clear Local Environment" msgstr "" @@ -563,6 +841,39 @@ msgid "" "privilege." msgstr "您沒有「@1」許可權,不能命名這個元件。" +#: advtrains_signals_japan/init.lua +msgid "Caution" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Clear (proceed)" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Danger (halt)" +msgstr "" + +#: advtrains_signals_japan/init.lua +#, fuzzy +msgid "Japanese signal pole" +msgstr "高速列車車廂" + +#: advtrains_signals_japan/init.lua +msgid "Reduced speed" +msgstr "" + +#: advtrains_signals_japan/init.lua +msgid "Restricted speed" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Distant Signal (" +msgstr "" + +#: advtrains_signals_muc_ubahn/init.lua +msgid "Munich U-Bahn Main Signal (" +msgstr "" + #: advtrains_train_industrial/init.lua msgid "Big Industrial Train Engine" msgstr "大型工業用火車頭" @@ -717,6 +1028,9 @@ msgstr "對稱道岔" #~ msgid "This position is protected!" #~ msgstr "這裡已被保護。" +#~ msgid "This track can not be changed." +#~ msgstr "您不能調整這段軌道。" + #~ msgid "Use Sneak+rightclick to bypass closed doors!" #~ msgstr "請使用潛行+右鍵上車。" diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index 10576c3..760c7da 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -7,6 +7,9 @@ -- An entity is ONLY spawned by update_trainpart_properties when it finds it useful. -- Only data that are only important to the entity itself are stored in the luaentity +-- Translation +S = attrans + -- TP delay when getting off wagon local GETOFF_TP_DELAY = 0.5 @@ -154,12 +157,12 @@ function wagon:ensure_init() end end if not self.noninitticks then - atwarn("wagon",self.id,"uninitialized init=",self.initialized) + atwarn("Wagon",self.id,S("Uninitialized init="),self.initialized) self.noninitticks=0 end self.noninitticks=self.noninitticks+1 if self.noninitticks>20 then - atwarn("wagon",self.id,"uninitialized, removing") + atwarn("Wagon",self.id,S("Uninitialized, removing")) self:destroy() else self.object:set_velocity({x=0,y=0,z=0}) @@ -182,7 +185,7 @@ function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direct return end if data.owner and puncher:get_player_name()~=data.owner and (not minetest.check_player_privs(puncher, {train_admin = true })) then - minetest.chat_send_player(puncher:get_player_name(), attrans("This wagon is owned by @1, you can't destroy it.", data.owner)); + minetest.chat_send_player(puncher:get_player_name(), S("This wagon is owned by @1, you can't destroy it.", data.owner)); return end @@ -201,25 +204,25 @@ function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direct if self.has_inventory then local inv=minetest.get_inventory({type="detached", name="advtrains_wgn_"..self.id}) if not inv then -- inventory is not initialized when wagon was never loaded - should never happen - atwarn("Destroying wagon with inventory, but inventory is not found? Shouldn't happen!") + atwarn(S("Destroying wagon with inventory, but inventory is not found? Shouldn't happen!")) return end for listname, _ in pairs(inv:get_lists()) do if not inv:is_empty(listname) then - minetest.chat_send_player(puncher:get_player_name(), attrans("The wagon's inventory is not empty.")); + minetest.chat_send_player(puncher:get_player_name(), S("The wagon's inventory is not empty.")); return end end end if #(self:train().trainparts)>1 then - minetest.chat_send_player(puncher:get_player_name(), attrans("Wagon needs to be decoupled from other wagons in order to destroy it.")); + minetest.chat_send_player(puncher:get_player_name(), S("Wagon needs to be decoupled from other wagons in order to destroy it.")); return end local pc=puncher:get_player_control() if not pc.sneak then - minetest.chat_send_player(puncher:get_player_name(), attrans("Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.")) + minetest.chat_send_player(puncher:get_player_name(), S("Warning: If you destroy this wagon, you only get some steel back! If you are sure, hold Sneak and left-click the wagon.")) return end @@ -240,7 +243,7 @@ function wagon:destroy() if self.id then local data = advtrains.wagons[self.id] if not data then - atwarn("wagon:destroy(): data is not set!") + atwarn(S(" wagon:destroy(): data is not set!")) return end @@ -367,15 +370,15 @@ function wagon:on_step(dtime) --show off-track information in outside text instead of notifying the whole server about this if train.off_track then - outside = outside .."\n!!! Train off track !!!" + outside = outside .."\n"..S("!!! Train off track !!!") end -- liquid container: display liquid contents in infotext if self.techage_liquid_capacity then if data.techage_liquid and data.techage_liquid.name then - outside = outside .."\nLiquid: "..data.techage_liquid.name..", "..data.techage_liquid.amount.." units" + outside = outside .."\n"..S("Liquid: ")..data.techage_liquid.name..", "..data.techage_liquid.amount..S(" units") else - outside = outside .."\nLiquid: empty" + outside = outside .."\n"..S("Liquid: empty") end end @@ -669,21 +672,21 @@ function wagon:on_rightclick(clicker) end end if self.has_inventory and self.get_inventory_formspec and advtrains.check_driving_couple_protection(pname, data.owner, data.whitelist) then - poss[#poss+1]={name=attrans("Show Inventory"), key="inv"} + poss[#poss+1]={name=S("Show Inventory"), key="inv"} end if self.seat_groups[sgr].driving_ctrl_access and advtrains.check_driving_couple_protection(pname, data.owner, data.whitelist) then - poss[#poss+1]={name=attrans("Onboard Computer"), key="bordcom"} + poss[#poss+1]={name=S("Onboard Computer"), key="bordcom"} end if data.owner==pname then - poss[#poss+1]={name=attrans("Wagon properties"), key="prop"} + poss[#poss+1]={name=S("Wagon properties"), key="prop"} end if not self.seat_groups[sgr].require_doors_open or self:train().door_open~=0 then - poss[#poss+1]={name=attrans("Get off"), key="off"} + poss[#poss+1]={name=S("Get off"), key="off"} else if clicker:get_player_control().sneak then - poss[#poss+1]={name=attrans("Get off (forced)"), key="off"} + poss[#poss+1]={name=S("Get off (forced)"), key="off"} else - poss[#poss+1]={name=attrans("(Doors closed)"), key="dcwarn"} + poss[#poss+1]={name=S("(Doors closed)"), key="dcwarn"} end end if #poss==0 then @@ -693,7 +696,7 @@ function wagon:on_rightclick(clicker) else local form = "size[5,"..1+(#poss).."]" for pos,ent in ipairs(poss) do - form = form .. "button_exit[0.5,"..(pos-0.5)..";4,1;"..ent.key..";"..ent.name.."]" + form = form.. "button_exit[0.5,"..(pos-0.5)..";4,1;"..ent.key..";"..ent.name.."]" end minetest.show_formspec(pname, "advtrains_seating_"..self.id, form) end @@ -712,7 +715,7 @@ function wagon:on_rightclick(clicker) end local doors_open = self:train().door_open~=0 or clicker:get_player_control().sneak - local allow, rsn=false, attrans("This wagon has no seats.") + local allow, rsn=false, S("This wagon has no seats.") for _,sgr in ipairs(self.assign_to_seat_group) do allow, rsn = self:check_seat_group_access(pname, sgr) if allow then @@ -723,16 +726,16 @@ function wagon:on_rightclick(clicker) self:get_on(clicker, seatid) return else - rsn=attrans("This wagon is full.") + rsn=S("This wagon is full.") end else - rsn=attrans("Doors are closed! (Try holding sneak key!)") + rsn=S("Doors are closed! (Try holding sneak key!)") end end end end end - minetest.chat_send_player(pname, rsn or attrans("You can't get on this wagon.")) + minetest.chat_send_player(pname, rsn or S("You can't get on this wagon.")) else self:show_get_on_form(pname) end @@ -858,7 +861,7 @@ function wagon:show_get_on_form(pname) end return end - local form, comma="size[5,8]label[0.5,0.5;"..attrans("Select seat:").."]textlist[0.5,1;4,6;seat;", "" + local form, comma="size[5,8]label[0.5,0.5;"..S("Select seat:").."]textlist[0.5,1;4,6;seat;", "" for seatno, seattbl in ipairs(self.seats) do local addtext, colorcode="", "" if data.seatp and data.seatp[seatno] then @@ -870,7 +873,7 @@ function wagon:show_get_on_form(pname) end form=form..";0,false]" if self.has_inventory and self.get_inventory_formspec then - form=form.."button_exit[1,7;3,1;inv;"..attrans("Show Inventory").."]" + form=form.."button_exit[1,7;3,1;inv;"..S("Show Inventory").."]" end minetest.show_formspec(pname, "advtrains_geton_"..self.id, form) end @@ -881,27 +884,27 @@ function wagon:show_wagon_properties(pname) button: save ]] local data = advtrains.wagons[self.id] - local form = "size[5,5]" - form = form.."label[0.2,0;"..attrans("This Wagon ID")..": "..self.id.." ("..data.owner..")]" - form = form .. "field[0.5,1;4.5,1;whitelist;Allow these players to access your wagon:;"..minetest.formspec_escape(data.whitelist or "").."]" - form = form .. "field[0.5,2;4.5,1;roadnumber;Wagon road number:;"..minetest.formspec_escape(data.roadnumber or "").."]" + local form="size[5,5]" + form=form.."label[0.2,0;"..S("This Wagon ID")..": "..self.id.." ("..data.owner..")]" + form = form.."field[0.5,1;4.5,1;whitelist;"..S("Allow these players to access your wagon:")..";"..minetest.formspec_escape(data.whitelist or "").."]" + form = form.."field[0.5,2;4.5,1;roadnumber;"..S("Wagon road number:")..";"..minetest.formspec_escape(data.roadnumber or "").."]" local fc = "" if data.fc then fc = table.concat(data.fc, "!") end - form = form .. "field[0.5,3;4.5,1;fc;Freight Code:;"..fc.."]" + form = form.. "field[0.5,3;4.5,1;fc;"..S("Freight Code:")..";"..fc.."]" if data.fc then if not data.fcind then data.fcind = 1 end if data.fcind > 1 then - form=form.."button[0.5,3.5;1,1;fcp;prev FC]" + form=form.."button[0.5,3.5;1,1;fcp;"..S("Prev FC").."]" end - form=form.."label[1.5,3.5;Current FC:]" + form=form.."label[1.5,3.5;"..S("Current FC: ").."]" local cur = data.fc[data.fcind] or "" form=form.."label[1.5,3.75;"..minetest.formspec_escape(cur).."]" - form=form.."button[3.5,3.5;1,1;fcn;next FC]" + form=form.."button[3.5,3.5;1,1;fcn;"..S("Next FC:").."]" end - form=form.."button_exit[0.5,4.5;4,1;save;"..attrans("Save wagon properties").."]" + form=form.."button_exit[0.5,4.5;4,1;save;"..S("Save wagon properties").."]" minetest.show_formspec(pname, "advtrains_prop_"..self.id, form) end @@ -986,30 +989,30 @@ function wagon:show_bordcom(pname) local linhei local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1]" - form=form.."textarea[7.5,0.05;10,1;;"..attrans("Train ID")..": "..(minetest.formspec_escape(train.id or ""))..";]" - form=form.."textarea[0.5,1.5;7,1;text_outside;"..attrans("Text displayed outside on train")..";"..(minetest.formspec_escape(train.text_outside or "")).."]" - form=form.."textarea[0.5,3;7,1;text_inside;"..attrans("Text displayed inside train")..";"..(minetest.formspec_escape(train.text_inside or "")).."]" - form=form.."field[7.5,1.75;3,1;line;"..attrans("Line")..";"..(minetest.formspec_escape(train.line or "")).."]" - form=form.."field[7.5,3.25;3,1;routingcode;"..attrans("Routingcode")..";"..(minetest.formspec_escape(train.routingcode or "")).."]" + form=form.."textarea[7.5,0.05;10,1;;"..S("Train ID")..": "..(minetest.formspec_escape(train.id or ""))..";]" + form=form.."textarea[0.5,1.5;7,1;text_outside;"..S("Text displayed outside on train")..";"..(minetest.formspec_escape(train.text_outside or "")).."]" + form=form.."textarea[0.5,3;7,1;text_inside;"..S("Text displayed inside train")..";"..(minetest.formspec_escape(train.text_inside or "")).."]" + form=form.."field[7.5,1.75;3,1;line;"..S("Line")..";"..(minetest.formspec_escape(train.line or "")).."]" + form=form.."field[7.5,3.25;3,1;routingcode;"..S("Routingcode")..";"..(minetest.formspec_escape(train.routingcode or "")).."]" --row 5 : train overview and autocoupling if train.velocity==0 then - form=form.."label[0.5,4;Train overview /coupling control:]" + form=form.."label[0.5,4;"..S("Train overview /coupling control:").."])" linhei=5 local pre_own, pre_wl, owns_any = nil, nil, minetest.check_player_privs(pname, "train_admin") for i, tpid in ipairs(train.trainparts) do local ent = advtrains.wagons[tpid] if ent then local roadnumber = ent.roadnumber or "" - form = form .. string.format("button[%d,%d;%d,%d;%s;%s]", i, linhei, 1, 0.2, "wgprp"..i, roadnumber) + form = form.. string.format("button[%d,%d;%d,%d;%s;%s]", i, linhei, 1, 0.2, "wgprp"..i, roadnumber) local ename = ent.type - form = form .. "item_image["..i..","..(linhei+0.5)..";1,1;"..ename.."]" + form = form.. "item_image["..i..","..(linhei+0.5)..";1,1;"..ename.."]" if i~=1 then if checklock(pname, ent.owner, pre_own, ent.whitelist, pre_wl) then - form = form .. "image_button["..(i-0.5)..","..(linhei+1.5)..";1,1;advtrains_discouple.png;dcpl_"..i..";]" + form = form.. "image_button["..(i-0.5)..","..(linhei+1.5)..";1,1;advtrains_discouple.png;dcpl_"..i..";]" end end if i == data.pos_in_trainparts then - form = form .. "box["..(i-0.1)..","..(linhei+0.4)..";1,1;green]" + form = form.. "box["..(i-0.1)..","..(linhei+0.4)..";1,1;green]" end pre_own = ent.owner pre_wl = ent.whitelist @@ -1018,24 +1021,24 @@ function wagon:show_bordcom(pname) end if train.movedir==1 then - form = form .. "label["..(#train.trainparts+1)..","..(linhei)..";-->]" + form = form.. "label["..(#train.trainparts+1)..","..(linhei)..";-->]" else - form = form .. "label[0.5,"..(linhei)..";<--]" + form = form.. "label[0.5,"..(linhei)..";<--]" end --check cpl_eid_front and _back of train local couple_front = checkcouple(train.cpl_front) local couple_back = checkcouple(train.cpl_back) if couple_front then - form = form .. "image_button[0.5,"..(linhei+1)..";1,1;advtrains_couple.png;cpl_f;]" + form = form.. "image_button[0.5,"..(linhei+1)..";1,1;advtrains_couple.png;cpl_f;]" end if couple_back then - form = form .. "image_button["..(#train.trainparts+0.5)..","..(linhei+1)..";1,1;advtrains_couple.png;cpl_b;]" + form = form.. "image_button["..(#train.trainparts+0.5)..","..(linhei+1)..";1,1;advtrains_couple.png;cpl_b;]" end else - form=form.."label[0.5,4.5;Train overview / coupling control is only shown when the train stands.]" + form=form.."label[0.5,4.5;"..S("Train overview / coupling control is only shown when the train stands.").."]" end - form = form .. "button[0.5,8;3,1;save;Save]" + form = form.. "button[0.5,8;3,1;save;"..S("Save").."]" -- Interlocking functionality: If the interlocking module is loaded, you can set the signal aspect -- from inside the train @@ -1045,14 +1048,14 @@ function wagon:show_bordcom(pname) local oci = train.lzb.checkpoints[i] if oci.udata and oci.udata.signal_pos then if advtrains.interlocking.db.get_sigd_for_signal(oci.udata.signal_pos) then - form = form .. "button[4.5,8;5,1;ilrs;Remote Routesetting]" + form = form.. "button[4.5,8;5,1;ilrs;"..S("Remote Routesetting").."]" break end end i=i+1 end if train.ars_disable then - form = form .. "button[4.5,7;5,1;ilarsenable;Clear 'Disable ARS' flag]" + form = form.. "button[4.5,7;5,1;ilarsenable;"..S("Clear 'Disable ARS' flag").."]" end end @@ -1269,7 +1272,7 @@ function wagon:seating_from_key_helper(pname, fields, no) self:show_bordcom(pname) end if fields.dcwarn then - minetest.chat_send_player(pname, attrans("Doors are closed. Use Sneak+rightclick to ignore the closed doors and get off.")) + minetest.chat_send_player(pname, S("Doors are closed. Use Sneak+rightclick to ignore the closed doors and get off.")) end if fields.off then self:get_off(no) @@ -1278,7 +1281,7 @@ end function wagon:check_seat_group_access(pname, sgr) local data = advtrains.wagons[self.id] if self.seat_groups[sgr].driving_ctrl_access and not (advtrains.check_driving_couple_protection(pname, data.owner, data.whitelist)) then - return false, attrans("You are not allowed to access the driver stand.") + return false, S("You are not allowed to access the driver stand.") end if self.seat_groups[sgr].driving_ctrl_access then advtrains.log("Drive", pname, self.object:get_pos(), self:train().text_outside) @@ -1298,7 +1301,7 @@ end function advtrains.safe_decouple_wagon(w_id, pname, try_run) if not minetest.check_player_privs(pname, "train_operator") then - minetest.chat_send_player(pname, "Missing train_operator privilege") + minetest.chat_send_player(pname, S("Missing train_operator privilege")) return false end local data = advtrains.wagons[w_id] @@ -1316,7 +1319,7 @@ function advtrains.safe_decouple_wagon(w_id, pname, try_run) end if not checklock(pname, data.owner, owdata.owner, data.whitelist, owdata.whitelist) then - minetest.chat_send_player(pname, "Not allowed to do this.") + minetest.chat_send_player(pname, S("Not allowed to do this.")) return false end @@ -1341,7 +1344,7 @@ function advtrains.get_wagon_prototype(data) end local rt, proto = advtrains.resolve_wagon_alias(wt) if not rt then - --atwarn("Unable to load wagon type",wt,", using placeholder") + --atwarn(S("Unable to load wagon type"),wt,S(", using placeholder")) rt = "advtrains:wagon_placeholder" proto = advtrains.wagon_prototypes[rt] end @@ -1378,7 +1381,7 @@ function advtrains.standard_inventory_formspec(self, pname, invname) local r = "size[8,11]".. "list["..invname..";box;0,0;8,3;]" if data.owner==pname then - r = r .. "button_exit[0,9;4,1;prop;"..attrans("Wagon properties").."]" + r = r .. "button_exit[0,9;4,1;prop;"..S("Wagon properties").."]" end r = r .. "list[current_player;main;0,5;8,4;]".. "listring[]" @@ -1435,7 +1438,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati return itemstack end if not minetest.check_player_privs(placer, {train_operator = true }) then - minetest.chat_send_player(pname, "You don't have the train_operator privilege.") + minetest.chat_send_player(pname, S("You don't have the train_operator privilege.")) return itemstack end if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pos, placer:get_player_name()) then @@ -1447,7 +1450,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati local prevpos = advtrains.get_adjacent_rail(pos, tconns, plconnid) if not prevpos then - minetest.chat_send_player(pname, "The track you are trying to place the wagon on is not long enough!") + minetest.chat_send_player(pname, S("The track you are trying to place the wagon on is not long enough!")) return end diff --git a/advtrains_line_automation/scheduler.lua b/advtrains_line_automation/scheduler.lua index 6025b02..5cba0a0 100644 --- a/advtrains_line_automation/scheduler.lua +++ b/advtrains_line_automation/scheduler.lua @@ -59,7 +59,7 @@ function sched.run() -- run it callbacks[elem.e](elem.d) else - atwarn("[lines][scheduler] No callback to handle schedule",elem) + atwarn("[lines][scheduler] "..S("No callback to handle schedule"),elem) end cnt=cnt+1 ucn = units_cnt[elem.u] diff --git a/advtrains_line_automation/stoprail.lua b/advtrains_line_automation/stoprail.lua index ba3977d..89f4a09 100644 --- a/advtrains_line_automation/stoprail.lua +++ b/advtrains_line_automation/stoprail.lua @@ -1,6 +1,8 @@ -- stoprail.lua -- adds "stop rail". Recognized by lzb. (part of behavior is implemented there) +-- Translation +S = attrans local function to_int(n) --- Disallow floating-point numbers @@ -28,7 +30,7 @@ local function show_stoprailform(pos, player) local pe = advtrains.encode_pos(pos) local pname = player:get_player_name() if minetest.is_protected(pos, pname) then - minetest.chat_send_player(pname, attrans("You are not allowed to configure this track.")) + minetest.chat_send_player(pname, S("You are not allowed to configure this track.")) return end @@ -51,19 +53,19 @@ local function show_stoprailform(pos, player) local form = "size[8,7]" form = form.."style[stn,ars;font=mono]" - form = form.."field[0.8,0.8;2,1;stn;"..attrans("Station Code")..";"..minetest.formspec_escape(stdata.stn).."]" - form = form.."field[2.8,0.8;5,1;stnname;"..attrans("Station Name")..";"..minetest.formspec_escape(stnname).."]" - form = form.."field[0.80,2.0;1.75,1;ddelay;"..attrans("Door Delay")..";"..minetest.formspec_escape(stdata.ddelay).."]" - form = form.."field[2.55,2.0;1.75,1;speed;"..attrans("Dep. Speed")..";"..minetest.formspec_escape(stdata.speed).."]" - form = form.."field[4.30,2.0;1.75,1;track;"..attrans("Track")..";"..minetest.formspec_escape(stdata.track).."]" - form = form.."field[6.05,2.0;1.75,1;wait;"..attrans("Stop Time")..";"..stdata.wait.."]" - form = form.."label[0.5,2.6;"..attrans("Door Side").."]" - form = form.."dropdown[0.51,3.0;2;doors;Left,Right,Closed;"..door_dropdown[stdata.doors].."]" - form = form.."checkbox[3.00,2.4;reverse;"..attrans("Reverse train")..";"..(stdata.reverse and "true" or "false").."]" - form = form.."checkbox[3.00,2.8;kick;"..attrans("Kick out passengers")..";"..(stdata.kick and "true" or "false").."]" - form = form.."checkbox[3.00,3.2;waitsig;"..attrans("Wait for signal to clear")..";"..(stdata.waitsig and "true" or "false").."]" - form = form.."textarea[0.8,4.2;7,2;ars;Trains stopping here (ARS rules);"..advtrains.interlocking.ars_to_text(stdata.ars).."]" - form = form.."button[0.5,6;7,1;save;"..attrans("Save").."]" + 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].."]" + 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) end @@ -74,7 +76,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local pos = advtrains.decode_pos(pe) if pos then if minetest.is_protected(pos, pname) then - minetest.chat_send_player(pname, attrans("You are not allowed to configure this track.")) + minetest.chat_send_player(pname, S("You are not allowed to configure this track.")) return end @@ -98,7 +100,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then stdata.stn = fields.stn else - minetest.chat_send_player(pname, attrans("Station code \"@1\" already exists and is owned by @2.", fields.stn, stn.owner)) + 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 @@ -112,7 +114,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if (stn.owner == pname or minetest.check_player_privs(pname, "train_admin")) then stn.name = fields.stnname else - minetest.chat_send_player(pname, attrans("This station is owned by @1. You are not allowed to edit its name.", stn.owner)) + minetest.chat_send_player(pname, S("This station is owned by @1. You are not allowed to edit its name.", stn.owner)) end end @@ -183,8 +185,8 @@ local adefunc = function(def, preset, suffix, rotation) 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 "Unknown Station" - train.text_inside = "Next Stop:\n"..stnname + 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 @@ -200,7 +202,7 @@ local adefunc = function(def, preset, suffix, rotation) 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 "Unknown Station" + 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 "") @@ -225,7 +227,7 @@ if minetest.get_modpath("advtrains_train_track") ~= nil then models_prefix="advtrains_dtrack", models_suffix=".b3d", shared_texture="advtrains_dtrack_shared_stop.png", - description=attrans("Station/Stop Track"), + description=S("Station/Stop Track"), formats={}, get_additional_definiton = adefunc, }, advtrains.trackpresets.t_30deg_straightonly) -- cgit v1.2.3