Merge branch 'master' into route_prog_rework

This commit is contained in:
orwell 2024-11-11 20:50:28 +01:00
commit 380c26f7a8
52 changed files with 4926 additions and 562 deletions

View File

@ -3,6 +3,12 @@ packages:
- git
- lua5.1
- luarocks
- curl
- minetest-server
- unzip
- wget
- lua-busted
- luajit
sources :
- https://git.sr.ht/~gpcf/advtrains
@ -26,4 +32,37 @@ tasks:
~/.luarocks/bin/mineunit -r
sed -n '/^File/,$p' luacov.report.out
mv luacov.report.out ~/$i.luacov.report.out
- install_mt_game : |
curl -L https://github.com/minetest/minetest_game/archive/master.zip -o master.zip
mkdir -p .minetest/games/
cd .minetest/games
unzip ../../master.zip
mv minetest_game-master minetest_game
- install_test_world: |
mkdir -p .minetest/worlds/
curl https://lifomaps.de/advtrains-test/testworld.tar.gz -o ~/testworld.tar.gz
cd .minetest/worlds/
tar xf ../../testworld.tar.gz
- run_unit_tests : |
cd advtrains/advtrains
busted
cd ../advtrains_interlocking
busted
cd ../serialize_lib
busted
- activate_test_env: |
cd advtrains
git merge --no-commit origin/luaatcdebug
- install_advtrains : |
mkdir .minetest/mods
cp -r advtrains .minetest/mods
cd .minetest/mods
git clone https://git.bananach.space/basic_trains.git/
- 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

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
.project
.settings
luacov.*
advtrains/locale/*.tr
advtrains/po/*~

View File

@ -106,7 +106,7 @@ local apn_func=function(pos)
-- FIX for long-persisting ndb bug: there's no node in parameter 2 of this function!
local meta=minetest.get_meta(pos)
if meta then
meta:set_string("infotext", attrans("ATC controller, unconfigured."))
meta:set_string("infotext", attrans("Unconfigured ATC controller"))
meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta))
end
end
@ -233,7 +233,7 @@ local matchptn={
advtrains.train_ensure_init(id, train)
-- no one minds if this failed... this shouldn't even be called without train being initialized...
else
atwarn(sid(id), attrans("ATC Reverse command warning: didn't reverse train, train moving!"))
atwarn(sid(id), attrans("ATC Reverse command warning: didn't reverse train, train moving."))
end
return 1
end,
@ -245,11 +245,11 @@ local matchptn={
end,
["K"] = function(id, train)
if train.door_open == 0 then
atwarn(sid(id), attrans("ATC Kick command warning: Doors closed"))
atwarn(sid(id), attrans("ATC Kick command warning: doors are closed."))
return 1
end
if train.velocity > 0 then
atwarn(sid(id), attrans("ATC Kick command warning: Train moving"))
atwarn(sid(id), attrans("ATC Kick command warning: train moving."))
return 1
end
local tp = train.trainparts

View File

@ -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<train.path_trk_b
if (train.off_track) then
minetest.chat_send_player(pname, "Back of train would end up off track, cancelling.")
minetest.chat_send_player(pname, attrans("Back of train would end up off track, cancelling."))
advtrains.remove_train(id)
return
end
@ -89,19 +89,19 @@ minetest.register_tool("advtrains:copytool", {
local le = pointed_thing.ref:get_luaentity()
if (le == nil) then
minetest.chat_send_player(user:get_player_name(), "No such lua entity!")
minetest.chat_send_player(user:get_player_name(), attrans("No such lua entity."))
return
end
local wagon = advtrains.wagons[le.id]
if (not (le.id and advtrains.wagons[le.id])) then
minetest.chat_send_player(user:get_player_name(), string.format("No such wagon: %s", le.id))
minetest.chat_send_player(user:get_player_name(), attrans("No such wagon: @1.", le.id))
return
end
local train = advtrains.trains[wagon.train_id]
if (not train) then
minetest.chat_send_player(user:get_player_name(), string.format("No such train: %s", wagon.train_id))
minetest.chat_send_player(user:get_player_name(), attrans("No such train: @1.", wagon.train_id))
return
end
@ -177,7 +177,7 @@ minetest.register_tool("advtrains:copytool", {
return
end
meta:set_string("clipboard", minetest.serialize(clipboard))
minetest.chat_send_player(user:get_player_name(), attrans("Train copied!"))
minetest.chat_send_player(user:get_player_name(), attrans("Train copied."))
return itemstack
end
})

View File

@ -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
@ -79,8 +93,9 @@ function advtrains.train_check_couples(train)
end
if not train.cpl_front then
-- recheck front couple
local front_trains, pos = advtrains.occ.get_occupations(train, atround(train.index) + CPL_CHK_DST)
local pos = advtrains.path_get(train, atround(train.index) + CPL_CHK_DST)
if advtrains.is_node_loaded(pos) then -- if the position is loaded...
local front_trains = advtrains.occ.reverse_lookup_sel(pos, "in_train")
for tid, idx in pairs(front_trains) do
local other_train = advtrains.trains[tid]
if not advtrains.train_ensure_init(tid, other_train) then
@ -109,8 +124,9 @@ function advtrains.train_check_couples(train)
end
if not train.cpl_back then
-- recheck back couple
local back_trains, pos = advtrains.occ.get_occupations(train, atround(train.end_index) - CPL_CHK_DST)
local pos = advtrains.path_get(train, atround(train.end_index) - CPL_CHK_DST)
if advtrains.is_node_loaded(pos) then -- if the position is loaded...
local back_trains = advtrains.occ.reverse_lookup_sel(pos, "in_train")
for tid, idx in pairs(back_trains) do
local other_train = advtrains.trains[tid]
if not advtrains.train_ensure_init(tid, other_train) then
@ -182,8 +198,8 @@ end
function advtrains.safe_couple_trains(train1, t1_is_front, train2, t2_is_front, pname)
if pname and not minetest.check_player_privs(pname, "train_operator") then
minetest.chat_send_player(pname, "Missing train_operator privilege")
return false
minetest.chat_send_player(pname, S("You are not allowed to couple trains without the train_operator privilege."))
return false
end
local wck_t1, wck_t2
@ -225,6 +241,15 @@ 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
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
@ -310,7 +335,7 @@ function advtrains.check_matching_coupler_types(t1, t1_front, t2, t2_front)
--atdebug("CMCT: t1",t1_cplt,"t2",t2_cplt,"")
-- if at least one of the trains has no couplers table, it always couples (fallback behavior and mode for universal shunters)
if not t1_cplt or not t2_cplt then
if minetest.settings:get_bool("advtrains_universal_couplers", false) or not t1_cplt or not t2_cplt then
return true
end
@ -326,11 +351,11 @@ function advtrains.check_matching_coupler_types(t1, t1_front, t2, t2_front)
for typ,_ in pairs(t1_cplt) do
table.insert(t1_cplhr, advtrains.coupler_types[typ] or typ)
end
if #t1_cplhr==0 then t1_cplhr[1]=attrans("<none>") end
if #t1_cplhr==0 then t1_cplhr[1]=attrans("<No coupler>") end
for typ,_ in pairs(t2_cplt) do
table.insert(t2_cplhr, advtrains.coupler_types[typ] or typ)
end
if #t2_cplhr==0 then t2_cplhr[1]=attrans("<none>") end
if #t2_cplhr==0 then t2_cplhr[1]=attrans("<No coupler>") end
return false, attrans("Can not couple: The couplers of the trains do not match (@1 and @2).", table.concat(t1_cplhr, ","), table.concat(t2_cplhr, ","))
end
@ -428,7 +453,7 @@ minetest.register_entity("advtrains:discouple", {
self.object:remove()
return
end
--getyaw seems to be a reliable method to check if an object is loaded...if it returns nil, it is not.
--get_yaw seems to be a reliable method to check if an object is loaded...if it returns nil, it is not.
if not self.wagon.object:get_yaw() then
self.object:remove()
return

View File

@ -6,7 +6,7 @@ core.register_craftitem("advtrains:boiler", {
core.register_craftitem("advtrains:driver_cab", {
description = attrans("driver's cab"),
description = attrans("Driver's cab"),
inventory_image = "advtrains_driver_cab.png",
})

View File

@ -21,6 +21,14 @@ minetest.register_craft({
},
})
--Wallmounted Signal
minetest.register_craft({
output = 'advtrains:signal_wall_l_off 2',
recipe = {
{'default:steel_ingot', 'default:steel_ingot', 'dye:red'},
{'', 'default:steel_ingot', ''},
{'default:steel_ingot', 'default:steel_ingot', 'dye:dark_green'},
},
})
minetest.register_craft({
output = 'advtrains:signal_wall_r_off 2',
recipe = {
@ -29,6 +37,15 @@ minetest.register_craft({
{'dye:dark_green', 'default:steel_ingot', 'default:steel_ingot'},
},
})
minetest.register_craft({
output = 'advtrains:signal_wall_t_off 2',
recipe = {
{'default:steel_ingot', '', 'default:steel_ingot'},
{'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
{'dye:dark_green', '', 'dye:red'},
},
})
--Wallmounted Signals can be converted into every orientation by shapeless crafting
minetest.register_craft({

View File

@ -51,6 +51,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
@ -181,7 +184,7 @@ function assertt(var, typ)
end
end
dofile(advtrains.modpath.."/helpers.lua");
dofile(advtrains.modpath.."/helpers.lua")
--dofile(advtrains.modpath.."/debugitems.lua");
advtrains.meseconrules =
@ -201,14 +204,20 @@ 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.formspec = dofile(advtrains.modpath.."/formspec.lua")
advtrains.texture = dofile(advtrains.modpath.."/texture.lua")
dofile(advtrains.modpath.."/path.lua")
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.."/track_reg_helper.lua")
dofile(advtrains.modpath.."/occupation.lua")
@ -479,6 +488,7 @@ advtrains.avt_save = function(remove_players_from_wagons)
"text_outside", "text_inside", "line", "routingcode",
"il_sections", "speed_restriction", "speed_restrictions_t", "is_shunt",
"path_ori_cp", "autocouple", "atc_wait_autocouple", "ars_disable",
"staticdata",
})
--then save it
tmp_trains[id]=v
@ -742,6 +752,21 @@ minetest.register_chatcommand("at_whereis",
end
end,
})
minetest.register_chatcommand("at_tp",
{
params = "<train id>",
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 = "<yes/no>",
@ -763,6 +788,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

1
advtrains/locale/README.md Symbolic link
View File

@ -0,0 +1 @@
../po/README.md

View File

@ -1,77 +0,0 @@
# textdomain: advtrains
This wagon is owned by @1, you can't destroy it.=Dieser Waggon gehört @1, du kannst 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: Du erhältst nur etwas Stahl zurück. Wenn du sicher bist, dass du den Waggon zerstören willst, halte 'Schleichen' und klicke links.
Show Inventory=Zeige Inventar
Select seat:=Wähle einen Sitzplatz aus:
ATC controller, unconfigured.=Zugbeeinflussungsschiene, nicht konfiguiert.
ATC controller=Zugbeeinflussungsschiene
ATC controller, mode @1@nChannel: @2=Zugbeeinflussungsschiene in Betriebsart "@1"@nKanal: @2
ATC controller, mode @1@nCommand: @2=Zugbeeinflussungsschiene in Betriebsart "@1"@nBefehl: @2
Command=Befehl
Command (on)=Befehl (wenn ein)
Digiline channel=Digiline-Kanal
Save=Speichern
ATC Reverse command warning: didn't reverse train, train moving!=Zugbeeinflussung - Warnung: Befehl 'R' nicht ausgeführt, Zug in Bewegung!
ATC command syntax error: I statement not closed: @1=Zugbeeinflussung - Syntaxfehler: I-Anweisung nicht geschlossen: @1
ATC command parse error: Unknown command: @1=Zugbeeinflussung - Fehler: Unbekannter Befehl: @1
This position is protected!=Diese Position ist geschützt!
You need to own at least one neighboring wagon to destroy this couple.=Du musst Besitzer eines angrenzenden Waggons sein, um hier abzukuppeln.
@1 Platform (low)=Niedriger @1-Bahnsteig
@1 Platform (high)=Hoher @1-Bahnsteig
off=aus
on=ein
Lampless Signal (@1)=Mechanisches Signal (@1)
Signal (@1)=Lichtsignal (@1)
Track Worker Tool@n@nLeft-click: change rail type (straight/curve/switch)@nRight-click: rotate rail/bumper/signal/etc.=Schienenwerkzeug@n@nLinksklick: Schienentyp ändern, Rechtsklick: Objekt drehen.
This node can't be rotated using the trackworker!=Kann diesen Block nicht mit dem Schienenwerkzeug drehen.
This node can't be changed using the trackworker!=Kann diesen Block nicht mit dem Schienenwerkzeug bearbeiten.
Can't place: not pointing at node=Kann nicht platzieren: Du zeigst nicht auf einen Block.
Can't place: space occupied!=Kann nicht platzieren: Platz besetzt.
Can't place: protected position!=Kann nicht platzieren: Position geschützt.
Can't place: Not enough slope items left (@1 required)=Kann nicht platzieren: nicht genug Steigungsblöcke, es werden insgesamt @1 benötigt.
Can't place: There's no slope of length @1=Kann nicht platzieren: Keine Steigung der Länge @1 definiert.
Can't place: no supporting node at upper end.=Kann nicht platzieren: kein unterstützender Block am Ende der Steigung.
Deprecated Track=ausrangierte Schiene, nicht verwenden.
Track=Schiene
Bumper=Prellbock
Detector Rail=Detektorschiene
Speed:=Geschw.:
Target:=Zielges.:
@1 Slope=@1 Steigung
Can't get on: wagon full or doors closed!=Kann nicht einsteigen: Waggon voll oder Türen geschlossen.
Use Sneak+rightclick to bypass closed doors!=Nutze Sneak+Rechtsklick, um die Türnotöffnung zu aktivieren und trotzdem einzusteigen.
Lock couples=Kupplungen sperren
Save wagon properties=Waggon-Einstellungen speichern
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=Türen sind geschlossen! Sneak+Rechtsklick, um die Türnotöffnung zu aktivieren und trotzdem auszusteigen.
Wagon properties=Waggon-Einstellungen
Get off=Aussteigen
Get off (forced)=Aussteigen (erzwingen)
(Doors closed)=(Türen geschlossen)
Access to @1=Zugang zu @1
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
Industrial Train Engine=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)
<none>=<keine>

View File

@ -1,107 +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.=警告: 如果你摧毁此车厢, 你只能拿到一些钢方块. 如果你确定要摧毁这个车厢,请按潜行键并左键单击此车厢.
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 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
This position is protected!=这里已被保护.
You need to own at least one neighboring wagon to destroy this couple.=你必须至少拥有其中一个车厢才能解耦这两个车厢.
This node can't be rotated using the trackworker!=你不能使用铁路调整工具旋转这个方块.
This node can't be changed using the trackworker!=你不能使用铁路调整工具调整这个方块.
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不支持长度为@1m的斜坡.
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!=请使用潜行+右键上车
Lock couples=锁定连接处
Doors are closed! Use Sneak+rightclick to ignore the closed doors and get off!=车门已关闭, 请使用潜行+右键单击下车
Access to @1=可前往@1
The clipboard couldn't access the metadata. Paste failed.=无法粘贴: 剪贴板无法访问元数据
The clipboard couldn't access the metadata. Copy failed.=无法复制: 剪贴板无法访问元数据
# 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=保存
# "off" and "on" can be translated differently depending on the context and are therefore not translated.
off=off
on=on
# Line automation
Station Code=车站代码
Station Name=车站名称
Door Delay=车门关闭时间
Departure 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=垂直交叉铁轨
45/90 Degree Diamond Crossing Track=45度交叉铁轨
Unloading Track=卸货铁轨
Loading Track=装货铁轨
Bumper=保险杠
Detector Rail=探测铁轨
@1 Slope=@1斜坡
@1 Platform (low)=50cm高的@1站台
@1 Platform (high)=1m高的@1站台
@1 Platform (45 degree)=1m高的@1站台 (45度)
Lampless Signal (@1)=臂板信号机 (@1)
Signal (@1)=信号灯 (@1)
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=地铁车厢

View File

@ -86,9 +86,10 @@ end
function o.set_item(train_id, pos, idx)
local t = occgetcreate(pos)
assert(idx)
local i = 1
while t[i] do
if t[i]==train_id then
if t[i]==train_id and t[i+1]==index then
break
end
i = i + 2
@ -98,25 +99,30 @@ function o.set_item(train_id, pos, idx)
end
function o.clear_item(train_id, pos)
function o.clear_all_items(train_id, pos)
local t = occget(pos)
if not t then return end
local i = 1
local moving = false
while t[i] do
if t[i]==train_id then
if moving then
-- if, for some occasion, there should be a duplicate entry, erase this one too
atwarn("Duplicate occupation entry at",pos,"for train",train_id,":",t)
i = i - 2
end
moving = true
table.remove(t, i)
table.remove(t, i)
else
i = i + 2
end
if moving then
t[i] = t[i+2]
t[i+1] = t[i+3]
end
end
function o.clear_specific_item(train_id, pos, index)
local t = occget(pos)
if not t then return end
local i = 1
while t[i] do
if t[i]==train_id and t[i+1]==index then
table.remove(t, i)
table.remove(t, i)
else
i = i + 2
end
i = i + 2
end
end
@ -143,64 +149,88 @@ function o.check_collision(pos, train_id)
return false
end
-- Gets a mapping of train id's to indexes of trains that share this path item with this train
-- The train itself will not be included.
-- If the requested index position is off-track, returns {}.
-- returns (table with train_id->index), position
function o.get_occupations(train, index)
local ppos, ontrack = advtrains.path_get(train, index)
if not ontrack then
atlog("Train",train.id,"get_occupations requested off-track",index)
return {}, ppos
end
-- Gets a mapping of train id's to indexes of trains that have a path item at this position
-- Note that the case where 2 or more indices are at a position only occurs if there is a track loop.
-- returns (table with train_id->{index1, index2...})
function o.reverse_lookup(ppos)
local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos)
if not t then return {} end
local r = {}
local i = 1
local train_id = train.id
while t[i] do
if t[i]~=train_id then
r[t[i]] = t[i+1]
end
if not r[t[i]] then r[t[i]] = {} end
table.insert(r[t[i]], t[i+1])
i = i + 2
end
return r
end
-- Gets a mapping of train id's to indexes of trains that have a path item at this position.
-- Quick variant: will only return one index per train (the latest one added)
-- returns (table with train_id->index)
function o.reverse_lookup_quick(ppos)
local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos)
if not t then return {} end
local r = {}
local i = 1
while t[i] do
r[t[i]] = t[i+1]
i = i + 2
end
return r
end
local OCC_CLOSE_PROXIMITY = 3
-- Gets a mapping of train id's to index of trains that have a path item at this position. Selects at most one index based on a given heuristic, or even none if it does not match the heuristic criterion
-- returns (table with train_id->index), position
-- "in_train": first index that lies between train index and end index
-- "train_at_node": first index where the train is standing on that node (like in_train but with +-0.5 added to index)
-- "first_ahead": smallest index that is > current index
-- "before_end"(default): smallest index that is > end index
-- "close_proximity": within 3 indices close to the train index and end_index
-- "any": just output the first index found and do not check further (also occurs if both "in_train" and "first_ahead" heuristics have failed
function o.reverse_lookup_sel(pos, heuristic)
if not heuristic then heuristic = "before_end" end
local om = o.reverse_lookup(pos)
local r = {}
for tid, idxs in pairs(om) do
r[tid] = idxs[1]
if heuristic~="any" then
--must run a heuristic
--atdebug("reverse_lookup_sel is running heuristic for", pos,heuristic,"idxs",table.concat(idxs,","))
local otrn = advtrains.trains[tid]
advtrains.train_ensure_init(tid, otrn)
local h_value
for _,idx in ipairs(idxs) do
if heuristic == "first_ahead" and idx > otrn.index and (not h_value or h_value>idx) then
h_value = idx
end
if heuristic == "before_end" and idx > otrn.end_index and (not h_value or h_value>idx) then
h_value = idx
end
if heuristic == "in_train" and idx < otrn.index and idx > otrn.end_index then
h_value = idx
end
if heuristic == "train_at_node" and idx < (otrn.index+0.5) and idx > (otrn.end_index-0.5) then
h_value = idx
end
if heuristic == "close_proximity" and idx < (otrn.index + OCC_CLOSE_PROXIMITY) and idx > (otrn.end_index - OCC_CLOSE_PROXIMITY) then
h_value = idx
end
end
r[tid] = h_value
--atdebug(h_value,"chosen")
end
end
return r, pos
end
-- Gets a mapping of train id's to indexes of trains that stand or drive over
-- returns (table with train_id->index)
function o.get_trains_at(ppos)
local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos)
if not t then return {} end
local r = {}
local i = 1
while t[i] do
local train = advtrains.trains[t[i]]
local idx = t[i+1]
if train.end_index - 0.5 <= idx and idx <= train.index + 0.5 then
r[t[i]] = idx
end
i = i + 2
end
return r
end
-- Gets a mapping of train id's to indexes of trains that have a path
-- generated over this node
-- returns (table with train_id->index)
function o.get_trains_over(ppos)
local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos)
if not t then return {} end
local r = {}
local i = 1
while t[i] do
local idx = t[i+1]
r[t[i]] = idx
i = i + 2
end
return r
return o.reverse_lookup_sel(pos, "train_at_node")
end
advtrains.occ = o

View File

@ -118,7 +118,7 @@ function advtrains.path_invalidate(train, ignore_lock)
if train.path then
for i,p in pairs(train.path) do
advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(p))
advtrains.occ.clear_all_items(train.id, advtrains.round_vector_floor_y(p))
end
end
train.path = nil
@ -161,7 +161,7 @@ function advtrains.path_invalidate_ahead(train, start_idx, ignore_when_passed)
-- leave current node in path, it won't change. What might change is the path onward from here (e.g. switch)
local i = idx + 1
while train.path[i] do
advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(train.path[i]))
advtrains.occ.clear_specific_item(train.id, advtrains.round_vector_floor_y(train.path[i]), i)
i = i+1
end
train.path_ext_f=idx
@ -391,7 +391,7 @@ local PATH_CLEAR_KEEP = 4
function advtrains.path_clear_unused(train)
local i
for i = train.path_ext_b, train.path_req_b - PATH_CLEAR_KEEP do
advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(train.path[i]))
advtrains.occ.clear_specific_item(train.id, advtrains.round_vector_floor_y(train.path[i]), i)
train.path[i] = nil
train.path_dist[i-1] = nil
train.path_cp[i] = nil
@ -432,18 +432,19 @@ end
-- Projects the path of "train" onto the path of "onto_train_id", and returns the index on onto_train's path
-- that corresponds to "index" on "train"'s path, as well as whether both trains face each other
-- index may be fractional
-- heuristic: see advtrains.occ.reverse_lookup_sel()
-- returns: res_index, trains_facing
-- returns nil when path can not be projected, either because trains are on different tracks or
-- node at "index" happens to be on a turnout and it's the wrong direction
-- Note - duplicate with similar functionality is in train_step_b() - that code combines train detection with projecting
function advtrains.path_project(train, index, onto_train_id)
function advtrains.path_project(train, index, onto_train_id, heuristic)
local base_idx = atfloor(index)
local frac_part = index - base_idx
local base_pos = advtrains.path_get(train, base_idx)
local base_cn = train.path_cn[base_idx]
local otrn = advtrains.trains[onto_train_id]
-- query occupation
local occ = advtrains.occ.get_trains_over(base_pos)
local occ = advtrains.occ.reverse_lookup_sel(base_pos, heuristic)
-- is wanted train id contained?
local ob_idx = occ[onto_train_id]
if not ob_idx then

70
advtrains/po/README.md Normal file
View File

@ -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.

632
advtrains/po/advtrains.pot Normal file
View File

@ -0,0 +1,632 @@
# 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 <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: advtrains\n"
"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n"
"POT-Creation-Date: 2023-10-09 11:02+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 "Unconfigured ATC controller"
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
#: advtrains_luaautomation/active_common.lua:48
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 are 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/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/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 "<No coupler>"
msgstr ""
#: advtrains/couple.lua:334
msgid "Can not couple: The couplers of the trains do not match (@1 and @2)."
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/protection.lua:7
msgid "Can place, remove and operate trains"
msgstr ""
#: advtrains/protection.lua:12
msgid ""
"Can place, remove and operate any train, regardless of owner, whitelist, or "
"protection"
msgstr ""
#: advtrains/protection.lua:18
msgid "Can place and dig tracks in unprotected areas"
msgstr ""
#: advtrains/protection.lua:24
msgid "Can operate turnouts and signals in unprotected areas"
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/signals.lua:63
msgid "Lampless Signal"
msgstr ""
#: advtrains/signals.lua:127
msgid "Signal"
msgstr ""
#: advtrains/signals.lua:191
msgid "Wallmounted Signal (left)"
msgstr ""
#: advtrains/signals.lua:192
msgid "Wallmounted Signal (right)"
msgstr ""
#: advtrains/signals.lua:193
msgid "Wallmounted Signal (top)"
msgstr ""
#: advtrains/signals.lua:281 advtrains/signals.lua:322
msgid "Andrew's Cross"
msgstr ""
#: advtrains/trackplacer.lua:313
msgid ""
"Track Worker Tool\n"
"\n"
"Left-click: change rail type (straight/curve/switch)\n"
"Right-click: rotate object"
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/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 slope: not pointing at node."
msgstr ""
#: advtrains/tracks.lua:658
msgid "Can't place slope: space occupied."
msgstr ""
#: advtrains/tracks.lua:711
msgid "Can't place slope: Not enough slope items left (@1 required)."
msgstr ""
#: advtrains/tracks.lua:714
msgid "Can't place slope: There's no slope of length @1."
msgstr ""
#: advtrains/tracks.lua:721
msgid "Can't place slope: no supporting node at upper end."
msgstr ""
#: advtrains/trainhud.lua:305
msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again."
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:692
msgid "This wagon has no seats."
msgstr ""
#: advtrains/wagons.lua:703
msgid "This wagon is full."
msgstr ""
#: advtrains/wagons.lua:706
msgid "Doors are closed! (Try holding sneak key!)"
msgstr ""
#: advtrains/wagons.lua:712
msgid "You can't get on this wagon."
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/wagons.lua:1250
msgid "You are not allowed to access the driver stand."
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:13
msgid "Point speed restriction: @1"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:14
msgid "Set point speed restriction:"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:30
msgid "You are not allowed to configure this track without the @1 privilege."
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:34
#: advtrains_line_automation/stoprail.lua:31
#: advtrains_line_automation/stoprail.lua:76
msgid "You are not allowed to configure this track."
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:64
msgid "Point Speed Restriction Track"
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_line_automation/stoprail.lua:97
msgid "Station code \"@1\" already exists and is owned by @2."
msgstr ""
#: advtrains_line_automation/stoprail.lua:111
msgid "This station is owned by @1. You are not allowed to edit its name."
msgstr ""
#: advtrains_line_automation/stoprail.lua:221
msgid "Station/Stop Track"
msgstr ""
#: advtrains_luaautomation/active_common.lua:17
msgid "Unconfigured LuaATC component"
msgstr ""
#: advtrains_luaautomation/active_common.lua:46
msgid "LuaATC Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:49
msgid "Clear Local Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:50
msgid "Code"
msgstr ""
#: advtrains_luaautomation/active_common.lua:64
msgid ""
"You are not allowed to configure this LuaATC component without the @1 "
"privilege."
msgstr ""
#: advtrains_luaautomation/active_common.lua:94
msgid "LuaATC component assigned to environment '@1'"
msgstr ""
#: advtrains_luaautomation/active_common.lua:96
msgid "LuaATC component assigned to an invalid environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:171
msgid "LuaATC component with error: @1"
msgstr ""
#: advtrains_luaautomation/init.lua:13
msgid ""
"Can place and configure LuaATC components, including execute potentially "
"harmful Lua code"
msgstr ""
#: advtrains_luaautomation/mesecon_controller.lua:211
msgid "LuaATC Mesecon Controller"
msgstr ""
#: advtrains_luaautomation/operation_panel.lua:11
msgid "LuaATC Operation Panel"
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:28
msgid ""
"Passive Component Naming Tool\n"
"\n"
"Right-click to name a passive component."
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:39
msgid ""
"You are not allowed to name LuaATC passive components without the @1 "
"privilege."
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:62
msgid "Set name of component (empty to clear)"
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 ""
#: 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 ""

724
advtrains/po/de.po Normal file
View File

@ -0,0 +1,724 @@
msgid ""
msgstr ""
"Project-Id-Version: advtrains\n"
"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n"
"POT-Creation-Date: 2023-10-09 11:02+0200\n"
"PO-Revision-Date: 2023-10-09 11:18+0200\n"
"Last-Translator: Y. Wang <yw05@forksworld.de>\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"
"X-Generator: Poedit 3.3.2\n"
#: advtrains/atc.lua:109
msgid "Unconfigured ATC controller"
msgstr "Nicht konfiguiertes 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
#: advtrains_luaautomation/active_common.lua:48
msgid "Save"
msgstr "Speichern"
#: advtrains/atc.lua:236
msgid "ATC Reverse command warning: didn't reverse train, train moving."
msgstr ""
"Zugbeeinflussung: Der Zug befindet sich in Bewegung und kann nicht umgekehrt "
"werden."
#: advtrains/atc.lua:248
msgid "ATC Kick command warning: doors are closed."
msgstr ""
"Zugbeeinflussung: Wegen geschlossener Türen werden Fahrgäste nicht zum "
"Ausstieg gezwungen."
#: advtrains/atc.lua:252
msgid "ATC Kick command warning: train moving."
msgstr ""
"Zugbeeinflussung: Der Zug befindet sich in Bewegung, Fahrgäste werden nicht "
"zum Ausstieg gezwungen."
#: 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/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/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_operator“-Privileg keine Züge ankuppeln."
#: advtrains/couple.lua:329 advtrains/couple.lua:333
msgid "<No coupler>"
msgstr "<Keine Kupplung vorhanden>"
#: 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/craft_items.lua:3
msgid "Boiler"
msgstr ""
#: advtrains/craft_items.lua:9
msgid "Driver's cab"
msgstr "Führerstand"
#: 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/protection.lua:7
msgid "Can place, remove and operate trains"
msgstr ""
#: advtrains/protection.lua:12
msgid ""
"Can place, remove and operate any train, regardless of owner, whitelist, or "
"protection"
msgstr ""
#: advtrains/protection.lua:18
msgid "Can place and dig tracks in unprotected areas"
msgstr ""
#: advtrains/protection.lua:24
msgid "Can operate turnouts and signals in unprotected areas"
msgstr ""
#: 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/signals.lua:63
msgid "Lampless Signal"
msgstr "Mechanisches Signal"
#: advtrains/signals.lua:127
msgid "Signal"
msgstr "Lichtsignal"
#: advtrains/signals.lua:191
msgid "Wallmounted Signal (left)"
msgstr "An der linken Seite montiertes Signal"
#: advtrains/signals.lua:192
msgid "Wallmounted Signal (right)"
msgstr "An der rechten Seite montiertes Signal"
#: advtrains/signals.lua:193
msgid "Wallmounted Signal (top)"
msgstr "An der Decke montiertes Signal"
#: advtrains/signals.lua:281 advtrains/signals.lua:322
msgid "Andrew's Cross"
msgstr "Andreaskreuz"
#: advtrains/trackplacer.lua:313
msgid ""
"Track Worker Tool\n"
"\n"
"Left-click: change rail type (straight/curve/switch)\n"
"Right-click: rotate object"
msgstr ""
"Gleiswerkzeug\n"
"\n"
"Linksklick: Gleistyp ändern\n"
"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/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 slope: not pointing at node."
msgstr "Es kann nicht platziert werden: Sie zeigen nicht auf einem Block."
#: advtrains/tracks.lua:658
msgid "Can't place slope: space occupied."
msgstr "Es kann nicht platziert werden: Diese Position ist besetzt."
#: advtrains/tracks.lua:711
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:714
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:721
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/trainhud.lua:305
msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again."
msgstr ""
#: 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 "Der Waggon muss abgekoppelt sein, damit Sie ihn abbauen können."
#: 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:692
msgid "This wagon has no seats."
msgstr "In diesem Waggon ist kein Sitzplatz vorhanden."
#: advtrains/wagons.lua:703
msgid "This wagon is full."
msgstr "Der Waggon ist voll."
#: advtrains/wagons.lua:706
msgid "Doors are closed! (Try holding sneak key!)"
msgstr "Die Türen sind geschlossen."
#: advtrains/wagons.lua:712
msgid "You can't get on this wagon."
msgstr "Sie können nicht in diesen Waggon einsteigen."
#: 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/wagons.lua:1250
msgid "You are not allowed to access the driver stand."
msgstr "Sie haben keinen Zugang zum Führerstand."
#: advtrains_interlocking/tsr_rail.lua:13
msgid "Point speed restriction: @1"
msgstr "Geschwindigkeitskontrolle: @1"
#: advtrains_interlocking/tsr_rail.lua:14
msgid "Set point speed restriction:"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:30
msgid "You are not allowed to configure this track without the @1 privilege."
msgstr "Sie dürfen ohne das „@1“-Privileg dieses Gleis nicht konfigurieren."
#: advtrains_interlocking/tsr_rail.lua:34
#: advtrains_line_automation/stoprail.lua:31
#: advtrains_line_automation/stoprail.lua:76
msgid "You are not allowed to configure this track."
msgstr "Sie dürfen dieses Gleis nicht konfigurieren."
#: advtrains_interlocking/tsr_rail.lua:64
msgid "Point Speed Restriction Track"
msgstr "Geschwindigkeitskontrollgleis"
#: advtrains_line_automation/stoprail.lua:54
msgid "Station Code"
msgstr "Kennzeichen 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 "Türseite"
#: advtrains_line_automation/stoprail.lua:62
msgid "Reverse train"
msgstr "Zug Umkehren"
#: advtrains_line_automation/stoprail.lua:63
msgid "Kick out passengers"
msgstr "Fahrgäste zum Ausstieg zwingen"
#: advtrains_line_automation/stoprail.lua:97
msgid "Station code \"@1\" already exists and is owned by @2."
msgstr ""
"Die Haltestelle mit dem Kennzeichen „@1“ ist bereits vorhanden und wird von "
"@2 verwaltet."
#: advtrains_line_automation/stoprail.lua:111
msgid "This station is owned by @1. You are not allowed to edit its name."
msgstr ""
"Diese Haltestelle wird von @1 verwaltet. Sie dürfen sie nicht umbenennen."
#: advtrains_line_automation/stoprail.lua:221
msgid "Station/Stop Track"
msgstr "Gleis zur Kennzeichnung einer Haltestelle"
#: advtrains_luaautomation/active_common.lua:17
msgid "Unconfigured LuaATC component"
msgstr "Nicht konfiguierter LuaATC-Bauteil"
#: advtrains_luaautomation/active_common.lua:46
msgid "LuaATC Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:49
msgid "Clear Local Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:50
msgid "Code"
msgstr ""
#: advtrains_luaautomation/active_common.lua:64
msgid ""
"You are not allowed to configure this LuaATC component without the @1 "
"privilege."
msgstr ""
"Sie dürfen ohne das „@1“-Privileg diesen LuaATC-Bauteil nicht konfigurieren."
#: advtrains_luaautomation/active_common.lua:94
msgid "LuaATC component assigned to environment '@1'"
msgstr ""
#: advtrains_luaautomation/active_common.lua:96
msgid "LuaATC component assigned to an invalid environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:171
msgid "LuaATC component with error: @1"
msgstr "LuaATC-Bauteil mit Fehlermeldung: @1"
#: advtrains_luaautomation/init.lua:13
msgid ""
"Can place and configure LuaATC components, including execute potentially "
"harmful Lua code"
msgstr ""
"Kann LuaATC-Bauteile platzieren und konfigurieren (auch evtl. schädliche "
"Programme ausführen)"
#: advtrains_luaautomation/mesecon_controller.lua:211
msgid "LuaATC Mesecon Controller"
msgstr ""
#: advtrains_luaautomation/operation_panel.lua:11
msgid "LuaATC Operation Panel"
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:28
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_luaautomation/pcnaming.lua:39
msgid ""
"You are not allowed to name LuaATC passive components without the @1 "
"privilege."
msgstr "Sie dürfen ohne das „@1“ keinen passiven LuaATC-Bauteil benennen."
#: advtrains_luaautomation/pcnaming.lua:62
msgid "Set name of component (empty to clear)"
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 "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"
#: 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"
#~ msgid ""
#~ "ATC controller, mode @1\n"
#~ "Channel: @2"
#~ msgstr ""
#~ "Zugbeeinflussungsgleis in Betriebsart „@1“\n"
#~ "Kanal: @2"
#~ msgid "Access to @1"
#~ msgstr "Zugang zu @1"
#~ 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 "Can't place: protected position!"
#~ msgstr "Es kann nicht platziert werden: diese Position ist geschützt."
#~ msgid "Default Seat"
#~ msgstr "Standardsitzplatz"
#~ msgid "Default Seat (driver stand)"
#~ msgstr "Standardsitzplatz (Führerstand)"
#~ msgid "Deprecated Track"
#~ msgstr "ausrangiertes Gleis, nicht verwenden."
#~ msgid "Lock couples"
#~ msgstr "Kupplungen sperren"
#~ msgid "Speed:"
#~ msgstr "Geschw.:"
#~ msgid "Target:"
#~ msgstr "Zielges.:"
#~ msgid "This position is protected!"
#~ msgstr "Diese Position ist geschützt!"
#~ msgid "Use Sneak+rightclick to bypass closed doors!"
#~ msgstr ""
#~ "Nutzen Sie Schleichen+Rechtsklick, um trotz geschlossener Türen "
#~ "einzusteigen."
#, fuzzy
#~ msgid "You are not allowed to modify this protected track."
#~ msgstr "Sie dürfen an geschützten Stellen kein Gleis bauen."
#~ 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."

728
advtrains/po/fr.po Normal file
View File

@ -0,0 +1,728 @@
msgid ""
msgstr ""
"Project-Id-Version: advtrains\n"
"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n"
"POT-Creation-Date: 2023-10-09 11:02+0200\n"
"PO-Revision-Date: 2024-11-02 21:31+0100\n"
"Last-Translator: Tanavit <tanavit@posto.ovh>\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"
"X-Generator: Poedit 2.4.2\n"
#: advtrains/atc.lua:109
msgid "Unconfigured ATC controller"
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
#: advtrains_luaautomation/active_common.lua:48
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 are closed."
msgstr "Avertissement commande ATC Éjecter : portes closes."
#: advtrains/atc.lua:252
msgid "ATC Kick command warning: train moving."
msgstr "Avertissement commande ATC Éjecter : train en mouvement."
#: 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/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/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 ""
"Vous n'êtes pas autorisé à coupler des trains sans le privilège "
"\"train_operator\"."
#: advtrains/couple.lua:329 advtrains/couple.lua:333
msgid "<No coupler>"
msgstr "<Pas de coupleur>"
#: 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/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/protection.lua:7
msgid "Can place, remove and operate trains"
msgstr "Possibilité de poser, retirer ou opérer les trains"
#: advtrains/protection.lua:12
msgid ""
"Can place, remove and operate any train, regardless of owner, whitelist, or "
"protection"
msgstr ""
"Possibilité de poser, retirer ou opérer un quelconque train, indépendamment "
"du propriétaire, de la liste blanche ou de protection"
#: advtrains/protection.lua:18
msgid "Can place and dig tracks in unprotected areas"
msgstr "Possibilité de poser ou retirer des voies dans les zones non protégées"
#: advtrains/protection.lua:24
msgid "Can operate turnouts and signals in unprotected areas"
msgstr ""
"Possibilité d'opérer des embranchements et signaux dans les zones non "
"protégées"
#: 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/signals.lua:63
msgid "Lampless Signal"
msgstr "Sémaphore"
#: advtrains/signals.lua:127
msgid "Signal"
msgstr "Signal"
#: advtrains/signals.lua:191
msgid "Wallmounted Signal (left)"
msgstr "Signal mural (gauche)"
#: advtrains/signals.lua:192
msgid "Wallmounted Signal (right)"
msgstr "Signal mural (droit)"
#: advtrains/signals.lua:193
msgid "Wallmounted Signal (top)"
msgstr "Signal mural (plafond)"
#: advtrains/signals.lua:281 advtrains/signals.lua:322
msgid "Andrew's Cross"
msgstr "Croix de Saint André"
#: advtrains/trackplacer.lua:313
msgid ""
"Track Worker Tool\n"
"\n"
"Left-click: change rail type (straight/curve/switch)\n"
"Right-click: rotate object"
msgstr ""
"Outil \"Trackworker\"\n"
"\n"
"Clic-Gauche : change le type de rail (droit/courbé/aiguillage)\n"
"\n"
"Clic-Droit : tourne l'objet"
#: 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/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 slope: not pointing at node."
msgstr "Placement impossible : ne pointe pas un nœud."
#: advtrains/tracks.lua:658
msgid "Can't place slope: space occupied."
msgstr "Placement impossible : espace occupé."
#: advtrains/tracks.lua:711
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:714
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:721
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/trainhud.lua:305
msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again."
msgstr ""
"Franchissement de signal rouge : examinez la situation et inversez le sens "
"de marche du train."
#: 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 ""
"Les wagons doivent être désaccouplés des autres pour pouvoir être détruits."
#: 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 "Ordinateur embarqué"
#: 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:692
msgid "This wagon has no seats."
msgstr "Ce wagon n'a pas de siège."
#: advtrains/wagons.lua:703
msgid "This wagon is full."
msgstr "Ce wagon est plein."
#: advtrains/wagons.lua:706
msgid "Doors are closed! (Try holding sneak key!)"
msgstr "Portes closes : (Essayez la \"sneak key\"!\")"
#: advtrains/wagons.lua:712
msgid "You can't get on this wagon."
msgstr "Montée impossible dans ce wagon."
#: 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/wagons.lua:1250
msgid "You are not allowed to access the driver stand."
msgstr "Accès interdit au poste de pilotage."
#: advtrains_interlocking/tsr_rail.lua:13
msgid "Point speed restriction: @1"
msgstr "Point de limitation de vitesse : @1"
#: advtrains_interlocking/tsr_rail.lua:14
msgid "Set point speed restriction:"
msgstr "Placez un point de limitation de vitesse :"
#: advtrains_interlocking/tsr_rail.lua:30
msgid "You are not allowed to configure this track without the @1 privilege."
msgstr "Vous n'êtes pas autorisé à configurer cette voie sans le privilège @1."
#: advtrains_interlocking/tsr_rail.lua:34
#: advtrains_line_automation/stoprail.lua:31
#: advtrains_line_automation/stoprail.lua:76
msgid "You are not allowed to configure this track."
msgstr "Vous n'êtes pas autorisé à configurer cette voie."
#: advtrains_interlocking/tsr_rail.lua:64
msgid "Point Speed Restriction Track"
msgstr "Voie de point de limitation de vitesse"
#: 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 "Coté d'ouvertures des portes"
#: advtrains_line_automation/stoprail.lua:62
msgid "Reverse train"
msgstr "Inversion du sens de marche"
#: advtrains_line_automation/stoprail.lua:63
msgid "Kick out passengers"
msgstr "Éjecter les passagers"
#: advtrains_line_automation/stoprail.lua:97
msgid "Station code \"@1\" already exists and is owned by @2."
msgstr "Le code de station \"@1\" existe et est possédé par @2."
#: advtrains_line_automation/stoprail.lua:111
msgid "This station is owned by @1. You are not allowed to edit its name."
msgstr ""
"Cette station est la propriété de @1. Vous n'êtes pas autorisé à modifier "
"son nom."
#: advtrains_line_automation/stoprail.lua:221
msgid "Station/Stop Track"
msgstr "Voie d'arrêt en station"
#: advtrains_luaautomation/active_common.lua:17
msgid "Unconfigured LuaATC component"
msgstr "Composant LuaATC non configuré"
#: advtrains_luaautomation/active_common.lua:46
msgid "LuaATC Environment"
msgstr "Environnement LuaATC"
#: advtrains_luaautomation/active_common.lua:49
msgid "Clear Local Environment"
msgstr "Effacer l'environnement LuaATC"
#: advtrains_luaautomation/active_common.lua:50
msgid "Code"
msgstr "Code"
#: advtrains_luaautomation/active_common.lua:64
msgid ""
"You are not allowed to configure this LuaATC component without the @1 "
"privilege."
msgstr "Vous ne pouvez configurer ce composant LuaATC sans le privilege @1."
#: advtrains_luaautomation/active_common.lua:94
msgid "LuaATC component assigned to environment '@1'"
msgstr "Composant LuaATC assigné à l'environnement '@1'"
#: advtrains_luaautomation/active_common.lua:96
msgid "LuaATC component assigned to an invalid environment"
msgstr "Composant LuaATC assigné à un environnement invalide"
#: advtrains_luaautomation/active_common.lua:171
msgid "LuaATC component with error: @1"
msgstr "Erreur @1 du composant LuaATC"
#: advtrains_luaautomation/init.lua:13
msgid ""
"Can place and configure LuaATC components, including execute potentially "
"harmful Lua code"
msgstr ""
"Permet le placement et la configuration de composants LuaATC avec risque "
"d'exécution de code Lua dangereux"
#: advtrains_luaautomation/mesecon_controller.lua:211
msgid "LuaATC Mesecon Controller"
msgstr "Commande Mesecon de LuaATC"
#: advtrains_luaautomation/operation_panel.lua:11
msgid "LuaATC Operation Panel"
msgstr "Panneau de commande de LuaATC"
#: advtrains_luaautomation/pcnaming.lua:28
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_luaautomation/pcnaming.lua:39
msgid ""
"You are not allowed to name LuaATC passive components without the @1 "
"privilege."
msgstr "Vous ne pouvez nommer un composant LuaATC passif sans le privilege @1."
#: advtrains_luaautomation/pcnaming.lua:62
msgid "Set name of component (empty to clear)"
msgstr "Nommer le composant (chaîne vide pour effacer)"
#: 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"
#: 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"
#~ msgid ""
#~ "ATC controller, mode @1\n"
#~ "Channel: @2"
#~ msgstr ""
#~ "Controlleur ATC, mode @1\n"
#~ "Canal : @2"
#~ msgid "Access to @1"
#~ msgstr "Accès à @1"
#~ msgid "Can't get on: wagon full or doors closed!"
#~ msgstr ""
#~ "Embarquement impossible : le wagon est plein ou ses portes sont closes !"
#~ msgid "Can't place: protected position!"
#~ msgstr "Placement impossible : emplacement protégé"
#~ msgid "Default Seat"
#~ msgstr "Siège par défaut"
#~ msgid "Default Seat (driver stand)"
#~ msgstr "Siège par défaut (poste de pilotage)"
#~ msgid "Deprecated Track"
#~ msgstr "Voie déconseillée"
#~ msgid "Lock couples"
#~ msgstr "Verrouiller l'accouplement"
#~ msgid "Speed:"
#~ msgstr "Vitesse : "
#~ msgid "Target:"
#~ msgstr "Destination : "
#, fuzzy
#~ msgid "This node can't be rotated using the trackworker,"
#~ msgstr "Ce nœud ne peut être tourné avec l'outil \"Trackworker\" !"
#~ msgid "This position is protected!"
#~ msgstr "Cet emplacement est protégé !"
#~ msgid "Use Sneak+rightclick to bypass closed doors!"
#~ msgstr ""
#~ "Utilisez \"Marcher lentement (Sneak)\" et Clic-Droit pour franchir les "
#~ "portes closes !"
#, fuzzy
#~ msgid "You are not allowed to modify this protected track."
#~ msgstr "Vous ne pouvez pas construire une voie à cet emplacement protégé"
#~ 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."

View File

@ -0,0 +1,28 @@
#!/bin/sh
# NOTE: Please make sure you also have basic_trains installed, as it uses attrans for historical reasons
PODIR=`dirname "$0"`
ATDIR="$PODIR/../.."
BTDIR="$ATDIR/../basic_trains"
POTFILE="$PODIR/advtrains.pot"
xgettext \
-D "$ATDIR" \
-D "$BTDIR" \
-d advtrains \
-o "$POTFILE" \
-p . \
-L lua \
--from-code=UTF-8 \
--sort-by-file \
--keyword='attrans' \
--keyword='S' \
--package-name='advtrains' \
--msgid-bugs-address='advtrains-discuss@lists.sr.ht' \
`find $ATDIR $BTDIR -name '*.lua' -printf '%P\n'` \
&&
for i in "$PODIR"/*.po; do
msgmerge -U \
--sort-by-file \
$i "$POTFILE"
done

696
advtrains/po/zh_CN.po Normal file
View File

@ -0,0 +1,696 @@
msgid ""
msgstr ""
"Project-Id-Version: advtrains\n"
"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n"
"POT-Creation-Date: 2023-10-09 11:02+0200\n"
"PO-Revision-Date: 2023-10-09 11:24+0200\n"
"Last-Translator: Y. Wang <yw05@forksworld.de>\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"
"X-Generator: Poedit 3.3.2\n"
#: advtrains/atc.lua:109
msgid "Unconfigured ATC controller"
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
#: advtrains_luaautomation/active_common.lua:48
msgid "Save"
msgstr "保存"
#: advtrains/atc.lua:236
msgid "ATC Reverse command warning: didn't reverse train, train moving."
msgstr "ATC 警告:火车正在移动,无法改变行车方向。"
#: advtrains/atc.lua:248
msgid "ATC Kick command warning: doors are closed."
msgstr "ATC 警告:车门已关闭,无法踢出乘客。"
#: advtrains/atc.lua:252
msgid "ATC Kick command warning: train moving."
msgstr "ATC 警告:火车正在移动,无法踢出乘客。"
#: 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/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/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 "<No coupler>"
msgstr "<没有车钩>"
#: advtrains/couple.lua:334
msgid "Can not couple: The couplers of the trains do not match (@1 and @2)."
msgstr "您无法连接这两节车厢:这两节车厢使用不同的车钩 (@1和@2)。"
#: 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/protection.lua:7
msgid "Can place, remove and operate trains"
msgstr ""
#: advtrains/protection.lua:12
msgid ""
"Can place, remove and operate any train, regardless of owner, whitelist, or "
"protection"
msgstr ""
#: advtrains/protection.lua:18
msgid "Can place and dig tracks in unprotected areas"
msgstr ""
#: advtrains/protection.lua:24
msgid "Can operate turnouts and signals in unprotected areas"
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/signals.lua:63
msgid "Lampless Signal"
msgstr "臂板信号机"
#: advtrains/signals.lua:127
msgid "Signal"
msgstr "信号灯"
#: advtrains/signals.lua:191
msgid "Wallmounted Signal (left)"
msgstr "壁挂式信号灯 (左侧)"
#: advtrains/signals.lua:192
msgid "Wallmounted Signal (right)"
msgstr "壁挂式信号灯 (右侧)"
#: advtrains/signals.lua:193
msgid "Wallmounted Signal (top)"
msgstr "悬挂式信号灯"
#: advtrains/signals.lua:281 advtrains/signals.lua:322
msgid "Andrew's Cross"
msgstr "铁路道口信号灯"
#: advtrains/trackplacer.lua:313
msgid ""
"Track Worker Tool\n"
"\n"
"Left-click: change rail type (straight/curve/switch)\n"
"Right-click: rotate object"
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/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 slope: not pointing at node."
msgstr "无法放置斜坡:您没有选择任何方块。"
#: advtrains/tracks.lua:658
msgid "Can't place slope: space occupied."
msgstr "无法放置斜坡:此区域已被占用。"
#: advtrains/tracks.lua:711
msgid "Can't place slope: Not enough slope items left (@1 required)."
msgstr "无法放置斜坡:您没有足够的铁路斜坡放置工具 (您总共需要@1个)"
#: advtrains/tracks.lua:714
msgid "Can't place slope: There's no slope of length @1."
msgstr "无法放置斜坡advtrains 不支持长度为@1米的斜坡。"
#: advtrains/tracks.lua:721
msgid "Can't place slope: no supporting node at upper end."
msgstr "无法放置斜坡:较高端没有支撑方块。"
#: advtrains/trainhud.lua:305
msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again."
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:692
msgid "This wagon has no seats."
msgstr "这节车厢没有座位。"
#: advtrains/wagons.lua:703
msgid "This wagon is full."
msgstr "车厢已满。"
#: advtrains/wagons.lua:706
msgid "Doors are closed! (Try holding sneak key!)"
msgstr ""
#: advtrains/wagons.lua:712
msgid "You can't get on this wagon."
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/wagons.lua:1250
msgid "You are not allowed to access the driver stand."
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:13
msgid "Point speed restriction: @1"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:14
msgid "Set point speed restriction:"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:30
msgid "You are not allowed to configure this track without the @1 privilege."
msgstr "您没有“@1”权限不能调整这段轨道。"
#: advtrains_interlocking/tsr_rail.lua:34
#: advtrains_line_automation/stoprail.lua:31
#: advtrains_line_automation/stoprail.lua:76
msgid "You are not allowed to configure this track."
msgstr "您不能调整这段轨道。"
#: advtrains_interlocking/tsr_rail.lua:64
msgid "Point Speed Restriction Track"
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_line_automation/stoprail.lua:97
msgid "Station code \"@1\" already exists and is owned by @2."
msgstr ""
#: advtrains_line_automation/stoprail.lua:111
msgid "This station is owned by @1. You are not allowed to edit its name."
msgstr ""
#: advtrains_line_automation/stoprail.lua:221
msgid "Station/Stop Track"
msgstr "车站轨道"
#: advtrains_luaautomation/active_common.lua:17
msgid "Unconfigured LuaATC component"
msgstr "LuaATC 部件 (未配置)"
#: advtrains_luaautomation/active_common.lua:46
msgid "LuaATC Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:49
msgid "Clear Local Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:50
msgid "Code"
msgstr ""
#: advtrains_luaautomation/active_common.lua:64
msgid ""
"You are not allowed to configure this LuaATC component without the @1 "
"privilege."
msgstr "您没有“@1”权限不能配置这个 LuaATC 部件。"
#: advtrains_luaautomation/active_common.lua:94
msgid "LuaATC component assigned to environment '@1'"
msgstr ""
#: advtrains_luaautomation/active_common.lua:96
msgid "LuaATC component assigned to an invalid environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:171
msgid "LuaATC component with error: @1"
msgstr ""
#: advtrains_luaautomation/init.lua:13
msgid ""
"Can place and configure LuaATC components, including execute potentially "
"harmful Lua code"
msgstr ""
#: advtrains_luaautomation/mesecon_controller.lua:211
msgid "LuaATC Mesecon Controller"
msgstr ""
#: advtrains_luaautomation/operation_panel.lua:11
msgid "LuaATC Operation Panel"
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:28
msgid ""
"Passive Component Naming Tool\n"
"\n"
"Right-click to name a passive component."
msgstr ""
"被动元件命名工具\n"
"\n"
"右键单击命名所选元件。"
#: advtrains_luaautomation/pcnaming.lua:39
msgid ""
"You are not allowed to name LuaATC passive components without the @1 "
"privilege."
msgstr "您没有“@1”权限不能命名被动元件。"
#: advtrains_luaautomation/pcnaming.lua:62
msgid "Set name of component (empty to clear)"
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 "地铁车厢"
#: 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 "探测轨道"
#~ msgid ""
#~ "ATC controller, mode @1\n"
#~ "Channel: @2"
#~ msgstr ""
#~ "ATC 控制器\n"
#~ "模式:@1\n"
#~ "频道:@2"
#~ msgid "Access to @1"
#~ msgstr "可前往@1"
#~ msgid "Can't get on: wagon full or doors closed!"
#~ msgstr "无法上车:车门已关闭或车厢已满。"
#~ msgid "Can't place: protected position!"
#~ msgstr "无法放置:此区域已被保护。"
#~ msgid "Default Seat"
#~ msgstr "默认座位"
#~ msgid "Default Seat (driver stand)"
#~ msgstr "默认座位 (司机座位)"
#~ msgid "Deprecated Track"
#~ msgstr "请不要使用"
#~ msgid "Lock couples"
#~ msgstr "锁定连接处"
#~ msgid "Speed:"
#~ msgstr "速度"
#~ msgid "Target:"
#~ msgstr "目标速度"
#, fuzzy
#~ msgid "This node can't be rotated using the trackworker,"
#~ msgstr "您不能使用铁路调整工具旋转这个方块。"
#~ msgid "This position is protected!"
#~ msgstr "这里已被保护。"
#~ msgid "Use Sneak+rightclick to bypass closed doors!"
#~ msgstr "请使用潜行+右键上车。"
#, fuzzy
#~ msgid "You are not allowed to modify this protected track."
#~ msgstr "这里已被保护,您不能在这里建造铁路。"
#~ msgid ""
#~ "You need to own at least one neighboring wagon to destroy this couple."
#~ msgstr "您必须至少拥有其中一节车厢才能分开这两节车厢。"

696
advtrains/po/zh_TW.po Normal file
View File

@ -0,0 +1,696 @@
msgid ""
msgstr ""
"Project-Id-Version: advtrains\n"
"Report-Msgid-Bugs-To: advtrains-discuss@lists.sr.ht\n"
"POT-Creation-Date: 2023-10-09 11:02+0200\n"
"PO-Revision-Date: 2023-10-09 11:31+0200\n"
"Last-Translator: Y. Wang <yw05@forksworld.de>\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"
"X-Generator: Poedit 3.3.2\n"
#: advtrains/atc.lua:109
msgid "Unconfigured ATC controller"
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
#: advtrains_luaautomation/active_common.lua:48
msgid "Save"
msgstr "儲存"
#: advtrains/atc.lua:236
msgid "ATC Reverse command warning: didn't reverse train, train moving."
msgstr "ATC 警告:火車正在移動,無法改變行車方向。"
#: advtrains/atc.lua:248
msgid "ATC Kick command warning: doors are closed."
msgstr "ATC 警告:車門已關閉,無法踢出乘客。"
#: advtrains/atc.lua:252
msgid "ATC Kick command warning: train moving."
msgstr "ATC 警告:火車正在移動,無法踢出乘客。"
#: 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/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/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 "<No coupler>"
msgstr "<無連結器>"
#: advtrains/couple.lua:334
msgid "Can not couple: The couplers of the trains do not match (@1 and @2)."
msgstr "您無法連結這兩節車廂:這兩節車廂使用不同的連結器 (@1和@2)。"
#: 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/protection.lua:7
msgid "Can place, remove and operate trains"
msgstr ""
#: advtrains/protection.lua:12
msgid ""
"Can place, remove and operate any train, regardless of owner, whitelist, or "
"protection"
msgstr ""
#: advtrains/protection.lua:18
msgid "Can place and dig tracks in unprotected areas"
msgstr ""
#: advtrains/protection.lua:24
msgid "Can operate turnouts and signals in unprotected areas"
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/signals.lua:63
msgid "Lampless Signal"
msgstr "臂木式號誌機"
#: advtrains/signals.lua:127
msgid "Signal"
msgstr "色燈號誌機"
#: advtrains/signals.lua:191
msgid "Wallmounted Signal (left)"
msgstr "壁掛式色燈號誌機 (左側)"
#: advtrains/signals.lua:192
msgid "Wallmounted Signal (right)"
msgstr "壁掛式色燈號誌機 (右側)"
#: advtrains/signals.lua:193
msgid "Wallmounted Signal (top)"
msgstr "懸掛式色燈號誌機"
#: advtrains/signals.lua:281 advtrains/signals.lua:322
msgid "Andrew's Cross"
msgstr "平交道號誌燈"
#: advtrains/trackplacer.lua:313
msgid ""
"Track Worker Tool\n"
"\n"
"Left-click: change rail type (straight/curve/switch)\n"
"Right-click: rotate object"
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/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 slope: not pointing at node."
msgstr "無法放置斜坡:您沒有選擇任何方塊。"
#: advtrains/tracks.lua:658
msgid "Can't place slope: space occupied."
msgstr "無法放置斜坡:此區域已被佔用。"
#: advtrains/tracks.lua:711
msgid "Can't place slope: Not enough slope items left (@1 required)."
msgstr "無法放置斜坡:您沒有足夠的鐵路斜坡放置工具 (您總共需要@1個)"
#: advtrains/tracks.lua:714
msgid "Can't place slope: There's no slope of length @1."
msgstr "無法放置斜坡advtrains 不支援長度為@1米的斜坡。"
#: advtrains/tracks.lua:721
msgid "Can't place slope: no supporting node at upper end."
msgstr "無法放置斜坡:較高階沒有支撐方塊。"
#: advtrains/trainhud.lua:305
msgid "OVERRUN RED SIGNAL! Examine situation and reverse train to move again."
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:692
msgid "This wagon has no seats."
msgstr "這節車廂沒有座位。"
#: advtrains/wagons.lua:703
msgid "This wagon is full."
msgstr "車廂已滿。"
#: advtrains/wagons.lua:706
msgid "Doors are closed! (Try holding sneak key!)"
msgstr ""
#: advtrains/wagons.lua:712
msgid "You can't get on this wagon."
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/wagons.lua:1250
msgid "You are not allowed to access the driver stand."
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:13
msgid "Point speed restriction: @1"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:14
msgid "Set point speed restriction:"
msgstr ""
#: advtrains_interlocking/tsr_rail.lua:30
msgid "You are not allowed to configure this track without the @1 privilege."
msgstr "您沒有「@1」許可權不能調整這段軌道。"
#: advtrains_interlocking/tsr_rail.lua:34
#: advtrains_line_automation/stoprail.lua:31
#: advtrains_line_automation/stoprail.lua:76
msgid "You are not allowed to configure this track."
msgstr "您不能調整這段軌道。"
#: advtrains_interlocking/tsr_rail.lua:64
msgid "Point Speed Restriction Track"
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_line_automation/stoprail.lua:97
msgid "Station code \"@1\" already exists and is owned by @2."
msgstr ""
#: advtrains_line_automation/stoprail.lua:111
msgid "This station is owned by @1. You are not allowed to edit its name."
msgstr ""
#: advtrains_line_automation/stoprail.lua:221
msgid "Station/Stop Track"
msgstr "車站軌道"
#: advtrains_luaautomation/active_common.lua:17
msgid "Unconfigured LuaATC component"
msgstr "LuaATC 元件 (未配置)"
#: advtrains_luaautomation/active_common.lua:46
msgid "LuaATC Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:49
msgid "Clear Local Environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:50
msgid "Code"
msgstr ""
#: advtrains_luaautomation/active_common.lua:64
msgid ""
"You are not allowed to configure this LuaATC component without the @1 "
"privilege."
msgstr "您沒有「@1」許可權不能配置這個 LuaATC 元件。"
#: advtrains_luaautomation/active_common.lua:94
msgid "LuaATC component assigned to environment '@1'"
msgstr ""
#: advtrains_luaautomation/active_common.lua:96
msgid "LuaATC component assigned to an invalid environment"
msgstr ""
#: advtrains_luaautomation/active_common.lua:171
msgid "LuaATC component with error: @1"
msgstr ""
#: advtrains_luaautomation/init.lua:13
msgid ""
"Can place and configure LuaATC components, including execute potentially "
"harmful Lua code"
msgstr ""
#: advtrains_luaautomation/mesecon_controller.lua:211
msgid "LuaATC Mesecon Controller"
msgstr ""
#: advtrains_luaautomation/operation_panel.lua:11
msgid "LuaATC Operation Panel"
msgstr ""
#: advtrains_luaautomation/pcnaming.lua:28
msgid ""
"Passive Component Naming Tool\n"
"\n"
"Right-click to name a passive component."
msgstr ""
"被動元件命名工具\n"
"\n"
"右鍵單擊命名所選元件。"
#: advtrains_luaautomation/pcnaming.lua:39
msgid ""
"You are not allowed to name LuaATC passive components without the @1 "
"privilege."
msgstr "您沒有「@1」許可權不能命名這個元件。"
#: advtrains_luaautomation/pcnaming.lua:62
msgid "Set name of component (empty to clear)"
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 "地鐵車廂"
#: 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 "探測軌道"
#~ msgid ""
#~ "ATC controller, mode @1\n"
#~ "Channel: @2"
#~ msgstr ""
#~ "ATC 控制器\n"
#~ "模式:@1\n"
#~ "頻道:@2"
#~ msgid "Access to @1"
#~ msgstr "可前往@1"
#~ msgid "Can't get on: wagon full or doors closed!"
#~ msgstr "無法上車:車門已關閉或車廂已滿。"
#~ msgid "Can't place: protected position!"
#~ msgstr "無法放置:此區域已被保護。"
#~ msgid "Default Seat"
#~ msgstr "預設座位"
#~ msgid "Default Seat (driver stand)"
#~ msgstr "預設座位 (司機座位)"
#~ msgid "Deprecated Track"
#~ msgstr "請不要使用"
#~ msgid "Lock couples"
#~ msgstr "鎖定連結處"
#~ msgid "Speed:"
#~ msgstr "速度"
#~ msgid "Target:"
#~ msgstr "目標速度"
#, fuzzy
#~ msgid "This node can't be rotated using the trackworker,"
#~ msgstr "您不能使用鐵路調整工具旋轉這個方塊。"
#~ msgid "This position is protected!"
#~ msgstr "這裡已被保護。"
#~ msgid "Use Sneak+rightclick to bypass closed doors!"
#~ msgstr "請使用潛行+右鍵上車。"
#, fuzzy
#~ msgid "You are not allowed to modify this protected track."
#~ msgstr "這裡已被保護,您不能在這裡建造鐵路。"
#~ msgid ""
#~ "You need to own at least one neighboring wagon to destroy this couple."
#~ msgstr "您必須至少擁有其中一節車廂才能分開這兩節車廂。"

185
advtrains/poconvert.lua Normal file
View File

@ -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,
}

View File

@ -4,24 +4,24 @@
-- Privileges to control TRAIN DRIVING/COUPLING
minetest.register_privilege("train_operator", {
description = "Without this privilege, a player can't do anything about trains, neither place or remove them nor drive or couple them (but he can build tracks if he has track_builder)",
description = attrans("Can place, remove and operate trains"),
give_to_singleplayer= true,
});
minetest.register_privilege("train_admin", {
description = "Player may drive, place or remove any trains from/to anywhere, regardless of owner, whitelist or protection",
description = attrans("Can place, remove and operate any train, regardless of owner, whitelist, or protection"),
give_to_singleplayer= true,
});
-- Privileges to control TRACK BUILDING
minetest.register_privilege("track_builder", {
description = "Player can place and/or dig rails not protected from him. If he also has protection_bypass, he can place/dig any rails",
description = attrans("Can place and dig tracks in unprotected areas"),
give_to_singleplayer= true,
});
-- Privileges to control OPERATING TURNOUTS/SIGNALS
minetest.register_privilege("railway_operator", {
description = "Player can operate turnouts and signals not protected from him. If he also has protection_bypass, he can operate any turnouts/signals",
description = attrans("Can operate turnouts and signals in unprotected areas"),
give_to_singleplayer= true,
});
@ -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

View File

@ -65,3 +65,6 @@ advtrains_save_interval (Save Interval) int 60 20 3600
# If enabled, trains only collide with nodes with "normal" drawtype.
advtrains_forgiving_collision (Forgiving Collision mode) bool false
# Enable universal couplers for wagons
# If enabled, wagons will bypass the checks that compare the coupler types when coupling.
advtrains_universal_couplers (Universal Couplers) bool false

View File

@ -59,7 +59,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,
@ -121,7 +121,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,
@ -174,6 +174,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 (left)"),
r = attrans("Wallmounted Signal (right)"),
t = attrans("Wallmounted Signal (top)"),
}
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",
@ -187,7 +192,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,
@ -287,7 +292,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,

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,40 @@
require "mineunit"
mineunit "core"
_G.advtrains = {
wagon_load_range = 32
}
sourcefile "wagons"
local myproto = {_test = true}
advtrains.register_wagon(":mywagon", myproto, "My wagon", "", false)
advtrains.register_wagon_alias(":myalias", ":mywagon")
advtrains.register_wagon_alias(":myotheralias", ":myalias")
local myotherproto = {_other = true}
advtrains.register_wagon(":noalias", myotherproto, "Not aliased wagon", "", false)
advtrains.register_wagon_alias(":noalias", ":mywagon")
advtrains.register_wagon_alias(":nilalias", ":nil")
advtrains.register_wagon_alias(":R1", ":R2")
advtrains.register_wagon_alias(":R2", ":R3")
advtrains.register_wagon_alias(":R3", ":R1")
describe("wagon alias system", function()
it("should work", function()
assert.same({":mywagon", myproto}, {advtrains.resolve_wagon_alias(":myalias")})
assert.equal(myproto, advtrains.wagon_prototypes[":myalias"])
assert.same({":mywagon", myproto}, {advtrains.resolve_wagon_alias(":myotheralias")})
end)
it("should respect wagon registration", function()
assert.same({":noalias", myotherproto}, {advtrains.resolve_wagon_alias(":noalias")})
end)
it("should handle recursive loops", function()
assert.same({}, {advtrains.resolve_wagon_alias(":R1")})
end)
it("should return nil for missing entries", function()
assert.same({}, {advtrains.resolve_wagon_alias(":what")})
assert.same({}, {advtrains.resolve_wagon_alias(":nilalias")})
end)
end)

228
advtrains/texture.lua Normal file
View File

@ -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-1)
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

View File

@ -230,10 +230,12 @@ function tp.place_track(pos, tpg, pname, yaw)
return true
end
-- TRACK WORKER --
minetest.register_craftitem("advtrains:trackworker",{
description = attrans("Track Worker Tool\n\nLeft-click: change rail type (straight/curve/switch)\nRight-click: rotate rail/bumper/signal/etc."),
description = attrans("Track Worker Tool\n\nLeft-click: change rail type (straight/curve/switch)\nRight-click: rotate object"),
groups = {cracky=1}, -- key=name, value=rating; rating=1..3.
inventory_image = "advtrains_trackworker.png",
wield_image = "advtrains_trackworker.png",

View File

@ -1,5 +1,7 @@
--trainhud.lua: holds all the code for train controlling
local T = advtrains.texture
advtrains.hud = {}
advtrains.hhud = {}
@ -8,6 +10,8 @@ advtrains.hud[player:get_player_name()] = nil
advtrains.hhud[player:get_player_name()] = nil
end)
local hud_type_key = minetest.features.hud_def_type_field and "type" or "hud_elem_type"
local mletter={[1]="F", [-1]="R", [0]="N"}
function advtrains.on_control_change(pc, train, flip)
@ -101,19 +105,21 @@ function advtrains.set_trainhud(name, text, driver)
if not player then
return
end
local drivertext = driver or ""
local driverhud = {
hud_elem_type = "image",
[hud_type_key] = "image",
name = "ADVTRAINS_DRIVER",
position = {x=0.5, y=1},
offset = {x=0,y=-170},
text = driver or "",
text = drivertext,
alignment = {x=0,y=-1},
scale = {x=1,y=1},}
scale = {x=1,y=1},
}
if not hud then
hud = {["driver"]={}}
hud = {}
advtrains.hud[name] = hud
hud.id = player:hud_add({
hud_elem_type = "text",
[hud_type_key] = "text",
name = "ADVTRAINS",
number = 0xFFFFFF,
position = {x=0.5, y=1},
@ -122,17 +128,22 @@ function advtrains.set_trainhud(name, text, driver)
scale = {x=200, y=60},
alignment = {x=0, y=-1},
})
hud.oldText=text
hud.driver = player:hud_add(driverhud)
hud.oldText = text
hud.oldDriver = drivertext
else
if hud.oldText ~= text then
player:hud_change(hud.id, "text", text)
hud.oldText=text
end
if hud.driver then
player:hud_change(hud.driver, "text", driver or "")
if hud.oldDriver ~= drivertext then
player:hud_change(hud.driver, "text", drivertext)
hud.oldDriver = drivertext
end
elseif driver then
hud.driver = player:hud_add(driverhud)
hud.oldDriver = drivertext
end
end
end
@ -147,7 +158,7 @@ function advtrains.set_help_hud(name, text)
hud = {}
advtrains.hhud[name] = hud
hud.id = player:hud_add({
hud_elem_type = "text",
[hud_type_key] = "text",
name = "ADVTRAINS_HELP",
number = 0xFFFFFF,
position = {x=1, y=0.3},
@ -184,138 +195,94 @@ 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
for i = 1, #oc do
if advtrains.interlocking then
local udata = oc[i].udata
if udata and udata.signal_pos then
local sigd = advtrains.interlocking.db.get_sigd_for_signal(udata.signal_pos)
if sigd then
local tcbs = advtrains.interlocking.db.get_tcbs(sigd) or {}
if tcbs.route_rsn then
table.insert(st, ("%s: %s"):format(minetest.pos_to_string(sigd.p), tcbs.route_rsn))
end
end
end
end
local spd = oc[i].speed
spd = advtrains.speed.min(spd, train.speed_restriction)
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",{

View File

@ -142,13 +142,8 @@ minetest.register_on_joinplayer(function(player)
local pname = player:get_player_name()
local id=advtrains.player_to_train_mapping[pname]
if id then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id then
local wdata = advtrains.wagons[wagon.id]
if wdata and wdata.train_id == id then
wagon:reattach_all()
end
end
for _, wagon in advtrains.wagon_entity_pairs_in_train(id) do
wagon:reattach_all()
end
end
end)
@ -160,12 +155,10 @@ minetest.register_on_dieplayer(function(player)
if id then
local train=advtrains.trains[id]
if not train then advtrains.player_to_train_mapping[pname]=nil return end
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
--when player dies, detach him from the train
--call get_off_plr on every wagon since we don't know which one he's on.
wagon:get_off_plr(pname)
end
for _, wagon in advtrains.wagon_entity_pairs_in_train(id) do
--when player dies, detach him from the train
--call get_off_plr on every wagon since we don't know which one he's on.
wagon:get_off_plr(pname)
end
-- just in case no wagon felt responsible for this player: clear train mapping
advtrains.player_to_train_mapping[pname] = nil
@ -270,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
@ -621,7 +618,7 @@ function advtrains.train_step_b(id, train, dtime)
local base_cn = train.path_cn[base_idx]
--atdebug(id,"Begin Checking for on-track collisions new_idx=",new_index_curr_tv,"base_idx=",base_idx,"base_pos=",base_pos,"base_cn=",base_cn)
-- query occupation
local occ = advtrains.occ.get_trains_over(base_pos)
local occ = advtrains.occ.reverse_lookup_sel(base_pos, "close_proximity")
-- iterate other trains
for otid, ob_idx in pairs(occ) do
if otid ~= id then
@ -651,7 +648,7 @@ function advtrains.train_step_b(id, train, dtime)
-- Phase 2 - project ref_index back onto our path and check again (necessary because there might be a turnout on the way and we are driving into the flank
if target_is_inside then
local our_index = advtrains.path_project(otrn, ref_index, id)
local our_index = advtrains.path_project(otrn, ref_index, id, "before_end")
--atdebug("Backprojected our_index",our_index)
if our_index and our_index <= new_index_curr_tv
and our_index >= train.index then --FIX: If train was already past the collision point in the previous step, there is no collision! Fixes bug with split_at_index
@ -805,9 +802,12 @@ function advtrains.train_step_c(id, train, dtime)
if is_loaded_area then
local objs = minetest.get_objects_inside_radius(rcollpos, 2)
for _,obj in ipairs(objs) do
if not obj:is_player() and obj:get_armor_groups().fleshy and obj:get_armor_groups().fleshy > 0
and obj:get_luaentity() and obj:get_luaentity().name~="signs_lib:text" then
obj:punch(obj, 1, { full_punch_interval = 1.0, damage_groups = {fleshy = 1000}, }, nil)
if not obj:is_player() then
local armor = obj:get_armor_groups()
local luaentity = obj:get_luaentity()
if armor.fleshy and armor.fleshy > 0 and luaentity and luaentity.name ~= "signs_lib:text" then
obj:punch(obj, 1, { full_punch_interval = 1.0, damage_groups = {fleshy = 1000}, }, nil)
end
end
end
end
@ -1101,8 +1101,17 @@ function advtrains.spawn_wagons(train_id)
if advtrains.position_in_range(pos, ablkrng) then
--atdebug("wagon",w_id,"spawning")
local wt = advtrains.get_wagon_prototype(data)
local wagon = minetest.add_entity(pos, wt):get_luaentity()
wagon:set_id(w_id)
local wobj = minetest.add_entity(pos, wt)
if not wobj then
atwarn("Failed to spawn wagon", w_id, "of type", wt)
else
local wagon = wobj:get_luaentity()
if not wagon then
atwarn("Wagon", w_id, "of type", wt, "spawned with nil luaentity")
else
wagon:set_id(w_id)
end
end
end
end
else
@ -1169,6 +1178,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
@ -1218,7 +1229,6 @@ function advtrains.invert_train(train_id)
advtrains.update_trainpart_properties(train_id, true)
-- recalculate path
advtrains.train_ensure_init(train_id, train)
-- If interlocking present, check whether this train is in a section and then set as shunt move after reversion
if advtrains.interlocking and train.il_sections and #train.il_sections > 0 then
@ -1244,7 +1254,7 @@ function advtrains.invalidate_all_paths(pos)
local tab
if pos then
-- if position given, check occupation system
tab = advtrains.occ.get_trains_over(pos)
tab = advtrains.occ.reverse_lookup_quick(pos)
else
tab = advtrains.trains
end
@ -1257,7 +1267,7 @@ end
-- Calls invalidate_path_ahead on all trains occupying (having paths over) this node
-- Can be called during train step.
function advtrains.invalidate_all_paths_ahead(pos)
local tab = advtrains.occ.get_trains_over(pos)
local tab = advtrains.occ.reverse_lookup_sel(pos, "first_ahead")
for id,index in pairs(tab) do
local train = advtrains.trains[id]

View File

@ -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

View File

@ -13,7 +13,13 @@ local GETOFF_TP_DELAY = 0.5
local IGNORE_WORLD = advtrains.IGNORE_WORLD
advtrains.wagons = {}
advtrains.wagon_prototypes = {}
advtrains.wagon_alias = {}
advtrains.wagon_prototypes = setmetatable({}, {
__index = function(t, k)
local _, proto = advtrains.resolve_wagon_alias(k)
return proto
end
})
advtrains.wagon_objects = {}
local unload_wgn_range = advtrains.wagon_load_range + 32
@ -200,7 +206,7 @@ function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direct
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(), attrans("The wagon's inventory is not empty."));
return
end
end
@ -280,7 +286,7 @@ function wagon:on_step(dtime)
local data = advtrains.wagons[self.id]
if not pos then
--atdebug("["..self.id.."][fatal] missing position (object:getpos() returned nil)")
--atdebug("["..self.id.."][fatal] missing position (object:get_pos() returned nil)")
return
end
@ -364,6 +370,15 @@ function wagon:on_step(dtime)
outside = outside .."\n!!! 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"
else
outside = outside .."\nLiquid: empty"
end
end
if self.infotext_cache~=outside then
self.object:set_properties({infotext=outside})
self.infotext_cache=outside
@ -689,7 +704,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, "Wagon has no seats!"
local allow, rsn=false, attrans("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
@ -700,16 +715,16 @@ function wagon:on_rightclick(clicker)
self:get_on(clicker, seatid)
return
else
rsn="Wagon is full."
rsn=attrans("This wagon is full.")
end
else
rsn="Doors are closed! (try holding sneak key!)"
rsn=attrans("Doors are closed! (Try holding sneak key!)")
end
end
end
end
end
minetest.chat_send_player(pname, attrans("Can't get on: "..rsn))
minetest.chat_send_player(pname, rsn or attrans("You can't get on this wagon."))
else
self:show_get_on_form(pname)
end
@ -805,8 +820,8 @@ function wagon:get_off(seatno)
end
--if not door_entry, or paths missing, fall back to old method
--atdebug("using fallback")
local objpos=advtrains.round_vector_floor_y(self.object:getpos())
local yaw=self.object:getyaw()
local objpos=advtrains.round_vector_floor_y(self.object:get_pos())
local yaw=self.object:get_yaw()
local isx=(yaw < math.pi/4) or (yaw > 3*math.pi/4 and yaw < 5*math.pi/4) or (yaw > 7*math.pi/4)
local offp
--abuse helper function
@ -859,6 +874,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 = ""
@ -883,7 +899,7 @@ end
--BordCom
local function checkcouple(ent)
if not ent or not ent:getyaw() then
if not ent or not ent:get_yaw() then
return nil
end
local le = ent:get_luaentity()
@ -962,6 +978,7 @@ 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 "")).."]"
@ -1079,12 +1096,11 @@ function wagon:handle_bordcom_fields(pname, formname, fields)
for i, tpid in ipairs(train.trainparts) do
if fields["dcpl_"..i] then
advtrains.safe_decouple_wagon(tpid, pname)
elseif fields["wgprp"..i] then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id==tpid and data.owner==pname then
wagon:show_wagon_properties(pname)
return
end
elseif fields["wgprp"..i] and data.owner==pname then
local wagon = advtrains.get_wagon_entity(tpid)
if wagon then
wagon:show_wagon_properties(pname)
return
end
end
end
@ -1130,44 +1146,48 @@ end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local uid=string.match(formname, "^advtrains_geton_(.+)$")
if uid then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id==uid then
local data = advtrains.wagons[wagon.id]
if fields.inv then
if wagon.has_inventory and wagon.get_inventory_formspec then
minetest.show_formspec(player:get_player_name(), "advtrains_inv_"..uid, wagon:get_inventory_formspec(player:get_player_name(), make_inv_name(uid)))
end
elseif fields.seat then
local val=minetest.explode_textlist_event(fields.seat)
if val and val.type~="INV" and not data.seatp[player:get_player_name()] then
--get on
wagon:get_on(player, val.index)
--will work with the new close_formspec functionality. close exactly this formspec.
minetest.show_formspec(player:get_player_name(), formname, "")
end
local wagon = advtrains.get_wagon_entity(uid)
if wagon then
local data = advtrains.wagons[wagon.id]
if fields.inv then
if wagon.has_inventory and wagon.get_inventory_formspec then
minetest.show_formspec(player:get_player_name(), "advtrains_inv_"..uid, wagon:get_inventory_formspec(player:get_player_name(), make_inv_name(uid)))
end
elseif fields.seat then
local val=minetest.explode_textlist_event(fields.seat)
if val and val.type~="INV" and not data.seatp[player:get_player_name()] then
--get on
wagon:get_on(player, val.index)
--will work with the new close_formspec functionality. close exactly this formspec.
minetest.show_formspec(player:get_player_name(), formname, "")
end
end
end
return true
end
uid=string.match(formname, "^advtrains_seating_(.+)$")
if uid then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id==uid then
local pname=player:get_player_name()
local no=wagon:get_seatno(pname)
if no then
if wagon.seat_groups then
wagon:seating_from_key_helper(pname, fields, no)
end
local wagon = advtrains.get_wagon_entity(uid)
if wagon then
local pname=player:get_player_name()
local no=wagon:get_seatno(pname)
if no then
if wagon.seat_groups then
wagon:seating_from_key_helper(pname, fields, no)
end
end
end
return true
end
uid=string.match(formname, "^advtrains_prop_(.+)$")
if uid then
local pname=player:get_player_name()
local data = advtrains.wagons[uid]
if pname~=data.owner and not minetest.check_player_privs(pname, {train_admin = true}) then
if not data then
return true
elseif pname~=data.owner and not minetest.check_player_privs(pname, {train_admin = true}) then
return true
end
if fields.save or not fields.quit then
@ -1189,29 +1209,32 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
wagon.show_wagon_properties({id=uid}, pname)
end
end
return true
end
uid=string.match(formname, "^advtrains_bordcom_(.+)$")
if uid then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id==uid then
wagon:handle_bordcom_fields(player:get_player_name(), formname, fields)
end
local wagon = advtrains.get_wagon_entity(uid)
if wagon then
wagon:handle_bordcom_fields(player:get_player_name(), formname, fields)
end
return true
end
uid=string.match(formname, "^advtrains_inv_(.+)$")
if uid then
local pname=player:get_player_name()
local data = advtrains.wagons[uid]
if fields.prop and data.owner==pname then
for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized and wagon.id==uid and data.owner==pname then
wagon:show_wagon_properties(pname)
--wagon:handle_bordcom_fields(player:get_player_name(), formname, fields)
end
local wagon = advtrains.get_wagon_entity(uid)
if wagon then
wagon:show_wagon_properties(pname)
--wagon:handle_bordcom_fields(player:get_player_name(), formname, fields)
end
end
return true
end
end)
function wagon:seating_from_key_helper(pname, fields, no)
local data = advtrains.wagons[self.id]
local sgr=self.seats[no].group
@ -1238,7 +1261,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, attrans("Doors are closed. Use Sneak+rightclick to ignore the closed doors and get off."))
end
if fields.off then
self:get_off(no)
@ -1247,10 +1270,10 @@ 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, "Not allowed to access a driver stand!"
return false, attrans("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:getpos(), self:train().text_outside)
advtrains.log("Drive", pname, self.object:get_pos(), self:train().text_outside)
end
return true
end
@ -1308,11 +1331,33 @@ function advtrains.get_wagon_prototype(data)
data.type = data.entity_name
data.entity_name = nil
end
if not wt or not advtrains.wagon_prototypes[wt] then
local rt, proto = advtrains.resolve_wagon_alias(wt)
if not rt then
atwarn("Unable to load wagon type",wt,", using placeholder")
wt="advtrains:wagon_placeholder"
rt = "advtrains:wagon_placeholder"
proto = advtrains.wagon_prototypes[rt]
end
return wt, advtrains.wagon_prototypes[wt]
return rt, proto
end
function advtrains.register_wagon_alias(src, dst)
advtrains.wagon_alias[src] = dst
end
local function recursive_resolve_alias(name, seen)
local prototype = rawget(advtrains.wagon_prototypes, name)
if prototype then
return name, prototype
end
local resolved = advtrains.wagon_alias[name]
if resolved and not seen[resolved] then
seen[name] = true
return recursive_resolve_alias(resolved, seen)
end
end
function advtrains.resolve_wagon_alias(name)
return recursive_resolve_alias(name, {})
end
function advtrains.standard_inventory_formspec(self, pname, invname)
@ -1359,13 +1404,23 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
groups = wagon_groups,
on_place = function(itemstack, placer, pointed_thing)
if not pointed_thing.type == "node" then
if pointed_thing.type ~= "node" then
return
end
local pos = pointed_thing.under
local node = minetest.get_node(pos)
local pointed_def = minetest.registered_nodes[node.name]
if pointed_def and pointed_def.on_rightclick then
local controls = placer:get_player_control()
if not controls.sneak then
return pointed_def.on_rightclick(pos, node, placer, itemstack, pointed_thing)
end
end
local pname = placer:get_player_name()
local node=minetest.get_node_or_nil(pointed_thing.under)
if not node then atprint("[advtrains]Ignore at placer position") return itemstack end
if node.name == "ignore" then atprint("[advtrains]Ignore at placer position") return itemstack end
local nodename=node.name
if(not advtrains.is_track(nodename)) then
atprint("no track here, not placing.")
@ -1375,14 +1430,14 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
minetest.chat_send_player(pname, "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(pointed_thing.under, placer:get_player_name()) then
if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pos, placer:get_player_name()) then
return itemstack
end
local tconns=advtrains.get_track_connections(node.name, node.param2)
local yaw = placer:get_look_horizontal()
local plconnid = advtrains.yawToClosestConn(yaw, tconns)
local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid)
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!")
return
@ -1390,7 +1445,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati
local wid = advtrains.create_wagon(sysname, pname)
local id=advtrains.create_new_train_at(pointed_thing.under, plconnid, 0, {wid})
local id=advtrains.create_new_train_at(pos, plconnid, 0, {wid})
if not advtrains.is_creative(pname) then
itemstack:take_item()
@ -1477,4 +1532,28 @@ function advtrains.get_wagon_at_index(train_id, w_index)
end
-- nothing found, dist must be further back
return nil
end
end
function advtrains.get_wagon_entity(wagon_id)
if not advtrains.wagons[wagon_id] then return end
local object = advtrains.wagon_objects[wagon_id]
if object then
return object:get_luaentity()
end
end
function advtrains.next_wagon_entity_in_train(train, i)
local wagon_id = train.trainparts[i + 1]
if wagon_id then
local wagon = advtrains.get_wagon_entity(wagon_id)
if wagon then
return i + 1, wagon
end
end
end
function advtrains.wagon_entity_pairs_in_train(train_id)
local train = advtrains.trains[train_id]
if not train then return function() end end
return advtrains.next_wagon_entity_in_train, train, 0
end

View File

@ -219,19 +219,32 @@ end
local player_rte_prog = {}
function advtrains.interlocking.init_route_prog(pname, sigd)
function advtrains.interlocking.init_route_prog(pname, sigd, default_route)
if not minetest.check_player_privs(pname, "interlocking") then
minetest.chat_send_player(pname, "Insufficient privileges to use this!")
return
end
player_rte_prog[pname] = {
local rp = {
origin = sigd,
route = {
name = "PROG["..pname.."]",
},
tmp_lcks = {},
}
advtrains.interlocking.visualize_route(sigd, player_rte_prog[pname].route, "prog_"..pname, player_rte_prog[pname].tmp_lcks, pname)
if default_route then
rp.route = table.copy(default_route)
-- "Step back one section", but keeping turnouts
local last_route = rp.route[#rp.route]
if last_route then
rp.tmp_lcks = last_route.locks
rp.route[#rp.route] = nil
end
rp.route.name = "PROG["..pname.."]"
else
rp.route = {
name = "PROG["..pname.."]"
}
rp.tmp_lcks = {}
end
player_rte_prog[pname] = rp
advtrains.interlocking.visualize_route(sigd, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
minetest.chat_send_player(pname, "Route programming mode active. Punch TCBs to add route segments, punch turnouts to lock them.")
end

View File

@ -25,7 +25,7 @@ function atil.show_route_edit_form(pname, sigd, routeid)
local route = tcbs.routes[routeid]
if not route then return end
local form = "size[9,10]label[0.5,0.2;Route overview]"
local form = "size[9,11]label[0.5,0.2;Route overview]"
form = form.."field[0.8,1.2;6.5,1;name;Route name;"..minetest.formspec_escape(route.name).."]"
form = form.."button[7.0,0.9;1.5,1;setname;Set]"
@ -114,11 +114,12 @@ function atil.show_route_edit_form(pname, sigd, routeid)
form = form.."button[3.5,6;2,1;noautogen;Clr Autogen]"
end
form = form.."button[5.5,6;3,1;delete;Delete Route]"
form = form.."button[5.5,7;3,1;newfrom;New From Route]"
--atdebug(route.ars)
form = form.."style[ars;font=mono]"
form = form.."textarea[0.8,7.3;5,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]"
form = form.."button[5.5,7.23;3,1;savears;Save ARS List]"
form = form.."textarea[0.8,8.3;5,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]"
form = form.."button[5.5,8.23;3,1;savears;Save ARS List]"
minetest.show_formspec(pname, "at_il_routeedit_"..minetest.pos_to_string(sigd.p).."_"..sigd.s.."_"..routeid, form)
@ -185,6 +186,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
table.remove(tcbs.routes, routeid)
advtrains.interlocking.show_signalling_form(sigd, pname)
end
if fields.newfrom then
advtrains.interlocking.init_route_prog(pname, sigd, route)
minetest.close_formspec(pname, formname)
tcbs.ars_ignore_next = nil
return
end
if fields.ars and fields.savears then
route.ars = atil.text_to_ars(fields.ars)

View File

@ -365,7 +365,13 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
end
if newrte then tcbs.routeset = newrte end
--atdebug("Setting:",tcbs.routeset)
local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
local succ, rsn, cbts, cblk
if tcbs.routes[tcbs.routeset] then
succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
else
succ = false
rsn = attrans("Route state changed.")
end
if not succ then
tcbs.route_rsn = rsn
--atdebug("Routesetting failed:",rsn)

View File

@ -494,6 +494,13 @@ minetest.register_entity("advtrains_interlocking:tcbmarker", {
static_save = false,
})
function advtrains.interlocking.remove_tcb_marker_pts(pts)
if markerent[pts] then
markerent[pts]:remove()
markerent[pts] = nil
end
end
function advtrains.interlocking.show_tcb_marker(pos)
--atdebug("showing tcb marker",pos)
local tcb = ildb.get_tcb(pos)
@ -517,9 +524,7 @@ function advtrains.interlocking.show_tcb_marker(pos)
end
local pts = advtrains.roundfloorpts(pos)
if markerent[pts] then
markerent[pts]:remove()
end
advtrains.interlocking.remove_tcb_marker_pts(pts)
local obj = minetest.add_entity(pos, "advtrains_interlocking:tcbmarker")
if not obj then return end
@ -628,14 +633,22 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle
strtab[#strtab+1] = clr .. minetest.formspec_escape(route.name)
end
form = form.."label[0.5,2.5;Routes:]"
form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",").."]"
form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",")
if sel_rte then
form = form .. ";" .. sel_rte .."]"
form = form.."button[0.5,6; 5,1;setroute;Set Route]"
form = form.."button[0.5,7;2,1;dsproute;Show]"
if hasprivs then
form = form.."button[3.5,7;2,1;editroute;Edit]"
if sel_rte > 1 then
form = form .. "button[5.5,4;0.5,0.3;moveup;↑]"
end
if sel_rte < #strtab then
form = form .. "button[5.5,4.7;0.5,0.3;movedown;↓]"
end
end
else
form = form .. "]"
if tcbs.ars_disabled then
form = form.."label[0.5,6 ;NOTE: ARS is disabled.]"
form = form.."label[0.5,6.5;Routes are not automatically set.]"
@ -772,6 +785,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.noauto then
tcbs.route_auto = false
end
if sel_rte and tcbs.routes[sel_rte]and not tcbs.routeset then
if fields.moveup then
if tcbs.routes[sel_rte - 1] then
tcbs.routes[sel_rte - 1], tcbs.routes[sel_rte] = tcbs.routes[sel_rte], tcbs.routes[sel_rte - 1]
sel_rte = sel_rte - 1
end
elseif fields.movedown then
if tcbs.routes[sel_rte + 1] then
tcbs.routes[sel_rte + 1], tcbs.routes[sel_rte] = tcbs.routes[sel_rte], tcbs.routes[sel_rte + 1]
sel_rte = sel_rte + 1
end
end
end
advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, true)
return

View File

@ -3,13 +3,15 @@
-- Simple rail whose only purpose is to place a TSR on the position, as a temporary solution until the timetable system covers everything.
-- This code resembles the code in lines/stoprail.lua
local S = attrans
local function updateform(pos)
local meta = minetest.get_meta(pos)
local pe = advtrains.encode_pos(pos)
local npr = advtrains.interlocking.npr_rails[pe] or 2
meta:set_string("infotext", "Point speed restriction: "..npr)
meta:set_string("formspec", "field[npr;Set point speed restriction:;"..npr.."]")
meta:set_string("infotext", S("Point speed restriction: @1",npr))
meta:set_string("formspec", "field[npr;"..S("Set point speed restriction:")..";"..npr.."]")
end
@ -25,11 +27,11 @@ local adefunc = function(def, preset, suffix, rotation)
on_receive_fields = function(pos, formname, fields, player)
local pname = player:get_player_name()
if not minetest.check_player_privs(pname, {interlocking=true}) then
minetest.chat_send_player(pname, "Interlocking privilege required!")
minetest.chat_send_player(pname, S("You are not allowed to configure this track without the @1 privilege.", "interlocking"))
return
end
if minetest.is_protected(pos, pname) then
minetest.chat_send_player(pname, "This rail is protected!")
minetest.chat_send_player(pname, S("You are not allowed to configure this track."))
minetest.record_protection_violation(pos, pname)
return
end
@ -59,7 +61,7 @@ if minetest.get_modpath("advtrains_train_track") ~= nil then
models_prefix="advtrains_dtrack",
models_suffix=".b3d",
shared_texture="advtrains_dtrack_shared_npr.png",
description="Point Speed Restriction Rail",
description=S("Point Speed Restriction Track"),
formats={},
get_additional_definiton = adefunc,
}, advtrains.trackpresets.t_30deg_straightonly)

View File

@ -28,7 +28,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, "Position is protected!")
minetest.chat_send_player(pname, attrans("You are not allowed to configure this track."))
return
end
@ -73,7 +73,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, "Position is protected!")
minetest.chat_send_player(pname, attrans("You are not allowed to configure this track."))
return
end
@ -94,7 +94,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, "Station code '"..fields.stn.."' does already exist and is owned by "..stn.owner)
minetest.chat_send_player(pname, attrans("Station code \"@1\" already exists and is owned by @2.", fields.stn, stn.owner))
show_stoprailform(pos,player)
return
end
@ -108,7 +108,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, "Not allowed to edit station name, owned by "..stn.owner)
minetest.chat_send_player(pname, attrans("This station is owned by @1. You are not allowed to edit its name.", stn.owner))
end
end
@ -218,7 +218,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="Station/Stop Rail",
description=attrans("Station/Stop Track"),
formats={},
get_additional_definiton = adefunc,
}, advtrains.trackpresets.t_30deg_straightonly)

View File

@ -93,6 +93,9 @@ Removes any pending interrupts of this node.
Make this active component send a digiline message on the specified channel.
Not available in init code.
- `trainparts(train_id)`
returns a table with the ids of the cars the train is composed of, or false if `train_id` is invalid. `train_id` can be replaced with `atc_id` when used in LuaATC Rails.
- `atc_send_to_train(<train_id>, <atc_command>)`
Sends the specified ATC command to the train specified by its train id. This happens regardless of where the train is in the world, and can be used to remote-control trains. Returns true on success. If the train ID does not exist, returns false and does nothing. See [atc_command.txt](../atc_command.txt) for the ATC command syntax.
@ -142,22 +145,16 @@ asp = {
-- the character of call_on and dead_end is purely informative
call_on = <boolean>, -- Call-on route, expect train in track ahead (not implemented yet)
dead_end = <boolean>, -- Route ends on a dead end (e.g. bumper) (not implemented yet)
w_speed = <integer>,
-- "Warning speed restriction". Supposed for short-term speed
-- restrictions which always override any other restrictions
-- imposed by "speed" fields, until lifted by a value of -1
-- (Example: german Langsamfahrstellen-Signale)
}
```
As of January 2020, the 'dst', 'call_on' and 'dead_end' fields are not used.
As of September 2024, the 'dst', 'call_on' and 'dead_end' fields are not used.
#### Lines
The advtrains_line_automation component adds a few contraptions that should make creating timeable systems easier.
Part of its functionality is also available in LuaATC:
- `rwt.*` - all Railway Time functions are included as documented in [the wiki](https://advtrains.de/wiki/doku.php?id=dev:lines:rwt)
- `rwt.*` - all Railway Time functions are included as documented in [the wiki](https://advtrains.de/wiki/doku.php?id=dev:api:railway_time_api)
- `schedule(rw_time, msg)`, `schedule_in(rw_dtime, msg)`
Schedules an event of type {type="schedule", schedule=true, msg=msg} at (resp. after) the specified railway time (which can be in any format). You can only schedule one event this way. (uses the new lines-internal scheduler)
@ -273,10 +270,17 @@ Each wagon has a current FC, indicating its next destination.
Returns a table with the entire FC list for each wagon in the train.
Command: `get_fc()`
Result: `{"", "foo!bar", "testing", "fc_1!fc_2!fc_3!?", "hello_world"}`
- `get_fc_index()`
Returns a table with the current FC index for each wagon in the train. Use in conjunction with the result from `get_fc()` to find a the current FC for a wagon.
Command: `get_fc_index()`
Result: `{1, 1, 1, 2, 1}`
- `set_fc(fc_list)`
- `set_fc(fc_list, reset_index)`
Overwrites the FC list according to a table `fc_list`. A false or nil entry will leave the wagon unaffected, however all others will be overwritten.
Useful for mass-programming freight trains that use FC-shunting instead of walking to each wagon individually.
Useful for mass-programming freight trains that use FC-shunting instead of walking to each wagon individually. If the new FC entry for a wagon is shorter than the old entry, the index will clip to the last FC in the new entry.
If `reset_index` is true, all Current FC values will reset to the first entry in the list, instead of remaining at the current index.
Example: train has FC lists: `"", "foo!bar", "testing", "fc_1!fc_2!fc_3!?", "hello_world"`
Command: `set_fc({"", "foo!turtle", nil, "4tehlulz", false})`
Result: `""` `"foo!turtle"` `"testing"` `"4tehlulz"` `"hello_world"`

View File

@ -1,4 +1,4 @@
local S = atltrans
local ac = {nodes={}}
@ -14,7 +14,7 @@ end
function ac.after_place_node(pos, player)
local meta=minetest.get_meta(pos)
meta:set_string("formspec", ac.getform(pos, meta))
meta:set_string("infotext", "LuaATC component, unconfigured.")
meta:set_string("infotext", S("Unconfigured LuaATC component"))
local ph=minetest.pos_to_string(pos)
--just get first available key!
for en,_ in pairs(atlatc.envs) do
@ -43,11 +43,11 @@ function ac.getform(pos, meta_p)
end
local form = "size["..atlatc.CODE_FORM_SIZE.."]"
.."style[code;font=mono]"
.."label[0,-0.1;Environment]"
.."label[0,-0.1;"..S("LuaATC Environment").."]"
.."dropdown[0,0.3;3;env;"..table.concat(envs_asvalues, ",")..";"..sel.."]"
.."button[5,0.2;2,1;save;Save]"
.."button[7,0.2;3,1;cle;Clear Local Env.]"
.."textarea[0.3,1.5;"..atlatc.CODE_FORM_SIZE..";code;Code;"..minetest.formspec_escape(code).."]"
.."button[5,0.2;2,1;save;"..S("Save").."]"
.."button[7,0.2;3,1;cle;"..S("Clear Local Environment").."]"
.."textarea[0.3,1.5;"..atlatc.CODE_FORM_SIZE..";code;"..S("Code")..";"..minetest.formspec_escape(code).."]"
.."label["..atlatc.CODE_FORM_ERRLABELPOS..";"..err.."]"
return form
end
@ -55,13 +55,17 @@ end
function ac.after_dig_node(pos, node, player)
advtrains.invalidate_all_paths(pos)
advtrains.ndb.clear(pos)
atlatc.interrupt.clear_ints_at_pos(pos)
if advtrains.lines and advtrains.lines.sched then
advtrains.lines.sched.discard_all(advtrains.encode_pos(pos))
end
local ph=minetest.pos_to_string(pos)
ac.nodes[ph]=nil
end
function ac.on_receive_fields(pos, formname, fields, player)
if not minetest.check_player_privs(player:get_player_name(), {atlatc=true}) then
minetest.chat_send_player(player:get_player_name(), "Missing privilege: atlatc - Operation cancelled!")
minetest.chat_send_player(player:get_player_name(), S("You are not allowed to configure this LuaATC component without the @1 privilege.", "atlatc"))
return
end
@ -91,9 +95,9 @@ function ac.on_receive_fields(pos, formname, fields, player)
meta:set_string("formspec", ac.getform(pos, meta))
if nodetbl.env then
meta:set_string("infotext", "LuaATC component, assigned to environment '"..nodetbl.env.."'")
meta:set_string("infotext", S("LuaATC component assigned to environment '@1'", nodetbl.env))
else
meta:set_string("infotext", "LuaATC component, invalid enviroment set!")
meta:set_string("infotext", S("LuaATC component assigned to an invalid environment"))
end
end
@ -168,7 +172,7 @@ function ac.run_in_env(pos, evtdata, customfct_p, ignore_no_code)
atlatc.active.nodes[ph].err=dataout
env:log("error", "LuaATC component at",ph,": LUA Error:",dataout)
if meta then
meta:set_string("infotext", "LuaATC component, ERROR:"..dataout)
meta:set_string("infotext", S("LuaATC component with error: @1", dataout))
end
--TODO temporary
--if customfct.atc_id then

25
advtrains_luaautomation/atc_rail.lua Executable file → Normal file
View File

@ -95,11 +95,19 @@ function r.fire_event(pos, evtdata, appr_internal)
if not train_id then return end
local fc_list = {}
for index,wagon_id in ipairs(train.trainparts) do
fc_list[index] = table.concat(advtrains.wagons[wagon_id].fc,"!") or ""
fc_list[index] = table.concat(advtrains.wagons[wagon_id].fc or {},"!")
end
return fc_list
end,
set_fc = function(fc_list)
get_fc_index = function()
if not train_id then return end
local fc_index_list = {}
for widx, wagon_id in ipars(train.trainparts) do
fc_index_list[widx] = advtrains.wagons[wagon_id].fcind or 1
end
return fc_index_list
end,
set_fc = function(fc_list,reset_index)
assertt(fc_list, "table")
if not train_id then return false end
-- safety type-check for entered values
@ -113,11 +121,12 @@ function r.fire_event(pos, evtdata, appr_internal)
if fc_list[index] then -- has FC to enter to this wagon
local data = advtrains.wagons[wagon_id]
if data then -- wagon actually exists
for _,wagon in pairs(minetest.luaentities) do -- find wagon entity
if wagon.is_wagon and wagon.initialized and wagon.id==wagon_id then
wagon.set_fc(data,fc_list[index]) -- overwrite to new FC
break -- no point cycling through every other entity. we found our wagon
end
--effectively copyied from wagons.lua, allowing for the :split function and reset_index
data.fc = fc_list[index]:split("!")
if reset_index or not data.fcind then
data.fcind = 1
elseif data.fcind > #data.fc then
data.fcind = #data.fc
end
end
end
@ -219,7 +228,7 @@ advtrains.register_tracks("default", {
models_prefix="advtrains_dtrack",
models_suffix=".b3d",
shared_texture="advtrains_dtrack_shared_atc.png",
description=atltrans("LuaATC Rail"),
description=atltrans("LuaATC Track"),
formats={},
get_additional_definiton = function(def, preset, suffix, rotation)
return {

View File

@ -153,6 +153,12 @@ local static_env = {
local pos=atlatc.pcnaming.resolve_pos(parpos, "interrupt_pos")
atlatc.interrupt.add(0, pos, {type="ext_int", ext_int=true, message=imesg})
end,
train_parts = function(train_id)
if not train_id then return false end
local train = advtrains.trains[train_id]
if not train then return false end
return table.copy(train.trainparts or {})
end,
-- sends an atc command to train regardless of where it is in the world
atc_send_to_train = function(train_id, command)
assertt(command, "string")
@ -164,6 +170,9 @@ local static_env = {
return false
end
end,
get_slowdown = function()
return advtrains.global_slowdown
end
}
-- If interlocking is present, enable route setting functions
@ -221,7 +230,7 @@ if advtrains.interlocking then
end
static_env.set_aspect = function(signal, asp)
local pos = atlatc.pcnaming.resolve_pos(signal)
return advtrains.interlocking.signal_set_aspect(pos)
return advtrains.interlocking.signal_set_aspect(pos,asp)
end
--section_occupancy()
@ -230,7 +239,7 @@ if advtrains.interlocking then
ts_id = tostring(ts_id)
local response = advtrains.interlocking.db.get_ts(ts_id)
if not response then return false end
return table.copy(response.trains)
return (response.trains and table.copy(response.trains)) or {}
end
end
@ -259,6 +268,11 @@ if advtrains.lines then
}
end
atlatc.register_function = function (name, f)
static_env[name] = f
end
for _, name in pairs(safe_globals) do
static_env[name] = _G[name]
end

View File

@ -2,15 +2,15 @@
-- Lua automation features for advtrains
-- Uses global table 'atlatc' (AdvTrains_LuaATC)
--TODO: re-add localization (if merging localization, discard this hunk please)
atltrans = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
atltrans = attrans
local S = atltrans
--Privilege
--Only trusted players should be enabled to build stuff which can break the server.
atlatc = { envs = {}}
minetest.register_privilege("atlatc", { description = "Player can place and modify LUA ATC components. Grant with care! Allows to execute bad LUA code.", give_to_singleplayer = false, default= false })
minetest.register_privilege("atlatc", { description = S("Can place and configure LuaATC components, including execute potentially harmful Lua code"), give_to_singleplayer = false, default= false })
--Size of code input forms in X,Y notation. Must be at least 10x10
atlatc.CODE_FORM_SIZE = "15,12"

View File

@ -6,6 +6,7 @@
-- From Mesecons mod https://mesecons.net/
-- (c) Jeija and Contributors
local S = atltrans
local BASENAME = "advtrains_luaautomation:mesecon_controller"
local rules = {
@ -207,7 +208,7 @@ for d = 0, 1 do
}
minetest.register_node(node_name, {
description = "LuaATC Mesecon Controller",
description = S("LuaATC Mesecon Controller"),
drawtype = "nodebox",
tiles = {
top,

3
advtrains_luaautomation/operation_panel.lua Executable file → Normal file
View File

@ -1,3 +1,4 @@
local S = atltrans
local function on_punch(pos,node,player)
atlatc.interrupt.add(0, pos, {type="punch", punch=true, name=player:get_player_name()})
@ -7,7 +8,7 @@ end
minetest.register_node("advtrains_luaautomation:oppanel", {
drawtype = "normal",
tiles={"atlatc_oppanel.png"},
description = "LuaATC operation panel",
description = S("LuaATC Operation Panel"),
groups = {
cracky = 1,
save_in_at_nodedb=1,

View File

@ -2,6 +2,8 @@
--a.k.a Passive component naming
--Allows to assign names to passive components, so they can be called like:
--setstate("iamasignal", "green")
local S = atltrans
atlatc.pcnaming={name_map={}}
function atlatc.pcnaming.load(stuff)
if type(stuff)=="table" then
@ -22,8 +24,11 @@ function atlatc.pcnaming.resolve_pos(pos, func_name)
error("Invalid position supplied to " .. (func_name or "???")..": " .. dump(pos))
end
local pcrename = {}
minetest.register_craftitem("advtrains_luaautomation:pcnaming",{
description = attrans("Passive Component Naming Tool\n\nRight-click to name a passive component."),
description = S("Passive Component Naming Tool\n\nRight-click to name a passive component."),
groups = {cracky=1}, -- key=name, value=rating; rating=1..3.
inventory_image = "atlatc_pcnaming.png",
wield_image = "atlatc_pcnaming.png",
@ -34,7 +39,7 @@ minetest.register_craftitem("advtrains_luaautomation:pcnaming",{
return
end
if not minetest.check_player_privs(pname, {atlatc=true}) then
minetest.chat_send_player(pname, "Missing privilege: atlatc")
minetest.chat_send_player(pname, S("You are not allowed to name LuaATC passive components without the @1 privilege.", "atlatc"))
return
end
if pointed_thing.type=="node" then
@ -43,6 +48,7 @@ minetest.register_craftitem("advtrains_luaautomation:pcnaming",{
minetest.record_protection_violation(pos, pname)
return
end
local node = advtrains.ndb.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
if node.name and (
@ -57,16 +63,17 @@ minetest.register_craftitem("advtrains_luaautomation:pcnaming",{
pn=name
end
end
minetest.show_formspec(pname, "atlatc_naming_"..minetest.pos_to_string(pos), "field[pn;Set name of component (empty to clear);"..minetest.formspec_escape(pn).."]")
pcrename[pname] = pos
minetest.show_formspec(pname, "atlatc_naming", "field[pn;"..S("Set name of component (empty to clear)")..";"..minetest.formspec_escape(pn).."]")
end
end
end,
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
local pts=string.match(formname, "^atlatc_naming_(.+)")
if pts then
local pos=minetest.string_to_pos(pts)
if fields.pn then
if formname == "atlatc_naming" then
local pname = player:get_player_name()
local pos=pcrename[pname]
if fields.pn and pos then
--first remove all occurences
for name, npos in pairs(atlatc.pcnaming.name_map) do
if vector.equals(npos, pos) then

View File

@ -333,6 +333,8 @@ for _, rtab in ipairs({
danger = {asp = { main = false, shunt = false }, n = "shuntd", ici=true},
shuntd = {asp = { main = false, shunt = true } , n = "danger"},
}) do
local sbox = table.copy(rtab.sbox)
sbox[5] = 0
minetest.register_node("advtrains_signals_ks:ra_"..typ.."_"..rot, {
description = "Ks Shunting Signal",
drawtype = "mesh",
@ -346,7 +348,11 @@ for _, rtab in ipairs({
paramtype2 = "facedir",
selection_box = {
type = "fixed",
fixed = {-1/4, -1/2, -1/4, 1/4, 0, 1/4}
fixed = {sbox, rotation_sbox}
},
collision_box = {
type = "fixed",
fixed = sbox,
},
groups = {
cracky = 2,

View File

@ -678,8 +678,45 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
local function load_wagon(wagon_id, node_inv, node_fc, unload)
local inv_modified = false
local w_inv=minetest.get_inventory({type="detached", name="advtrains_wgn_"..wagon_id})
if w_inv and w_inv:get_list("box") then
local wagon_data = advtrains.wagons[wagon_id]
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(node_inv:get_list("main")) do
if w_inv:get_list("box") and w_inv:room_for_item("box", item) then
w_inv:add_item("box", item)
node_inv:remove_item("main", item)
if item.name ~= "" then inv_modified = true end
end
end
else
for _, item in ipairs(w_inv:get_list("box")) do
if node_inv:get_list("main") and node_inv:room_for_item("main", item) then
w_inv:remove_item("box", item)
node_inv:add_item("main", item)
if item.name ~= "" then inv_modified = true end
end
end
end
end
end
return inv_modified
end
local function train_load(pos, train_id, unload)
local function load_entire_train(pos, train_id, unload) -- flood load when not in an active area
if advtrains.is_node_loaded(pos) then -- leave the loading to the nodetimer if area is loaded
return
end
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
@ -692,43 +729,60 @@ local function train_load(pos, train_id, unload)
--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
local node_inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
if node_inv and train.velocity <= 2 then
for _, wagon_id in ipairs(train.trainparts) do
load_wagon(wagon_id, node_inv, node_fc, unload)
end
end
end
local function load_wagon_on_timer(pos, unload) -- loading ramp when in an active area
if not advtrains.is_node_loaded(pos) then -- leave the loading for the flood load function. we're out of area
return true -- reset the nodetimer until the node is loaded again
end
local tid, tidx = advtrains.get_train_at_pos(pos)
if not tid or tid == "" then
return true
end -- no train to load.
local train = advtrains.trains[tid]
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 true
end
local node_fc = minetest.get_meta(pos):get_string("fc") or ""
if node_fc == "#" then
--track section is disabled
return true
end
local node_inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
if node_inv and train.velocity <= 2 then
local _, wagon_id, wagon_data = advtrains.get_wagon_at_index(tid, tidx)
if wagon_id then
local inv_modified = load_wagon(wagon_id, node_inv, node_fc, unload)
if inv_modified then
if advtrains.wagon_prototypes[advtrains.get_wagon_prototype(wagon_data)].set_textures then
local wagon_object = advtrains.wagon_objects[wagon_id]
if wagon_object and wagon_data then
local ent = wagon_object:get_luaentity()
if ent and ent.set_textures then
ent:set_textures(wagon_data)
end
end
end
end
end
end
return true
end
local nodetimer_interval = minetest.settings:get("advtrains_loading_track_timer") or 1
local function start_nodetimer(pos)
local timer = minetest.get_node_timer(pos)
timer:start(nodetimer_interval)
end
advtrains.register_tracks("default", {
nodename_prefix="advtrains:dtrack_unload",
@ -747,9 +801,16 @@ advtrains.register_tracks("default", {
on_rightclick = function(pos, node, player)
show_fc_formspec(pos, player)
end,
after_place_node = function(pos)
advtrains.ndb.update(pos)
start_nodetimer(pos)
end,
on_timer = function(pos)
return load_wagon_on_timer(pos, true)
end,
advtrains = {
on_train_enter = function(pos, train_id)
train_load(pos, train_id, true)
load_entire_train(pos, train_id, true)
end,
},
}
@ -772,9 +833,16 @@ advtrains.register_tracks("default", {
on_rightclick = function(pos, node, player)
show_fc_formspec(pos, player)
end,
after_place_node = function(pos)
advtrains.ndb.update(pos)
start_nodetimer(pos)
end,
on_timer = function(pos)
return load_wagon_on_timer(pos, false)
end,
advtrains = {
on_train_enter = function(pos, train_id)
train_load(pos, train_id, false)
load_entire_train(pos, train_id, false)
end,
},
}
@ -788,7 +856,6 @@ if minetest.get_modpath("basic_materials") then
elseif minetest.get_modpath("technic") then
loader_core = "technic:control_logic_unit"
end
--print("Loader Core: "..loader_core)
minetest.register_craft({
type="shapeless",

View File

@ -0,0 +1,4 @@
# Set the nodetimer delay for the loading tracks.
# A longer delay may cause wagons to be missed if the pass over too fast.
# A shorter delay may cause lag as wagons are checked multiple times as they pass over.
advtrains_loading_track_timer (Loading Track Timer) int 1