aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorywang <yw05@forksworld.de>2021-11-03 18:55:31 +0100
committerywang <yw05@forksworld.de>2021-11-07 13:49:01 +0100
commitbe2f37a0678c66278d1c491b8f1250a8a3be9feb (patch)
treeff592e9890892b0d0c6c9dc9b5e8ec81f76a956c
parent22994705235dfcdfbdc9966a9ba037d657188b5a (diff)
downloadadvtrains-be2f37a0678c66278d1c491b8f1250a8a3be9feb.tar.gz
advtrains-be2f37a0678c66278d1c491b8f1250a8a3be9feb.tar.bz2
advtrains-be2f37a0678c66278d1c491b8f1250a8a3be9feb.zip
Support different types of speed restrictions; add documentation
-rw-r--r--.dir-locals.el5
-rw-r--r--advtrains/doc/advtrains_speed_lessp.3advtrains.md15
-rw-r--r--advtrains/doc/advtrains_speed_merge_aspect.3advtrains.md18
-rw-r--r--advtrains/init.lua4
-rw-r--r--advtrains/spec/speed_spec.lua70
-rw-r--r--advtrains/speed.lua88
-rw-r--r--advtrains/trainlogic.lua5
-rw-r--r--advtrains_interlocking/approach.lua9
-rw-r--r--advtrains_signals_ks/doc/advtrains_signals_ks.7advtrains.md60
-rwxr-xr-xadvtrains_signals_ks/init.lua42
10 files changed, 309 insertions, 7 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..57aae07
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,5 @@
+((nil (tab-width . 8))
+ (lua-mode (indent-tabs-mode . t)
+ (lua-indent-level . 8)
+ (lua-indent-close-paren-align . nil)
+ (lua-indent-nested-block-content-align . nil)))
diff --git a/advtrains/doc/advtrains_speed_lessp.3advtrains.md b/advtrains/doc/advtrains_speed_lessp.3advtrains.md
new file mode 100644
index 0000000..165d028
--- /dev/null
+++ b/advtrains/doc/advtrains_speed_lessp.3advtrains.md
@@ -0,0 +1,15 @@
+% advtrains.speed.lessp(3advtrains) | Advtrains Developer's Manual
+
+# NAME
+`advtrains.speed.lessp`, `advtrains.speed.greaterp`, `advtrains.speed.not_lessp`, `advtrains.speed_not_greaterp`, `advtrains.speed.equalp`, `advtrains.speed.not_equalp`, `advtrains.speed.max`, `advtrains.speed.min` - speed restriction comparison functions
+
+# SYNOPSIS
+Each function takes two arguments and returns a boolean or (for `advtrains.speed.max` and `advtrains.speed.min`) a valid speed limit
+
+# DESCRIPTION
+
+The functions above correspond to the arithmetic `<`, `>`, `>=`, `<=`, `==`, `~=` operators and the `math.max` and `math.min` functions, respectively. The constants `nil` and `false` are treated as -1.
+
+# NOTES
+
+These functions are trivial to implement and the implementation can be easily embedded into existing code. They are simply provided for convenience.
diff --git a/advtrains/doc/advtrains_speed_merge_aspect.3advtrains.md b/advtrains/doc/advtrains_speed_merge_aspect.3advtrains.md
new file mode 100644
index 0000000..02e83ea
--- /dev/null
+++ b/advtrains/doc/advtrains_speed_merge_aspect.3advtrains.md
@@ -0,0 +1,18 @@
+% advtrains.speed.set_restriction(3advtrains) | Advtrains Developer's Manual
+
+# NAME
+`advtrains.speed.set_restriction`, `advtrains.speed.merge_aspect` - modify speed restriction
+
+# SYNOPSIS
+* `advtrains.speed.set_restriction(train, rtype, rval)`
+* `advtrains.speed.merge_aspect(train, asp)`
+
+# DESCRIPTION
+
+The `advtrains.speed.set_restriction` function sets the speed restriction of type `rtype` of `train` to `rval` and updates the speed restriction value to the strictest speed restriction in the table, or `nil` if all speed restrictions are `nil` or `-1`. If the speed restriction table does not exist, it is created with the `"main"` speed restriction being the speed restriction value of `train`.
+
+The `advtrains.speed.merge_aspect` function merges the main aspect of `asp` into the speed restriction table with the same procedure described above. If the signal aspect table does not provide the type of speed restriction, the restriction type `"main"` is assumed.
+
+# SIDE EFFECTS
+
+Both functions modify `train.speed_restriction` and `train.speed_restrictions_t`.
diff --git a/advtrains/init.lua b/advtrains/init.lua
index 0882237..a7e5764 100644
--- a/advtrains/init.lua
+++ b/advtrains/init.lua
@@ -198,6 +198,8 @@ advtrains.meseconrules =
advtrains.fpath=minetest.get_worldpath().."/advtrains"
+advtrains.speed = dofile(advtrains.modpath.."/speed.lua")
+
dofile(advtrains.modpath.."/path.lua")
dofile(advtrains.modpath.."/trainlogic.lua")
dofile(advtrains.modpath.."/trainhud.lua")
@@ -467,7 +469,7 @@ advtrains.avt_save = function(remove_players_from_wagons)
"trainparts", "recently_collided_with_env",
"atc_brake_target", "atc_wait_finish", "atc_command", "atc_delay", "door_open",
"text_outside", "text_inside", "line", "routingcode",
- "il_sections", "speed_restriction", "is_shunt",
+ "il_sections", "speed_restriction", "speed_restrictions_t", "is_shunt",
"points_split", "autocouple", "atc_wait_autocouple", "ars_disable",
})
--then save it
diff --git a/advtrains/spec/speed_spec.lua b/advtrains/spec/speed_spec.lua
new file mode 100644
index 0000000..0f0365f
--- /dev/null
+++ b/advtrains/spec/speed_spec.lua
@@ -0,0 +1,70 @@
+package.path = "../?.lua;" .. package.path
+advtrains = {}
+_G.advtrains = advtrains
+local speed = require("speed")
+
+describe("Arithmetic functions on speed restrictions", function()
+ it("should work", function()
+ local a = math.random()
+ local b = math.random(20)
+ -- This test is basically a "typo check"
+ assert.is_true (speed.lessp(a, b))
+ assert.is_false(speed.greaterp(a, b))
+ assert.is_false(speed.not_lessp(a, b))
+ assert.is_true (speed.not_greaterp(a, b))
+ assert.is_false(speed.lessp(a, a))
+ assert.is_false(speed.greaterp(a, a))
+ assert.is_true (speed.equalp(a, a))
+ assert.is_false(speed.not_equalp(a, a))
+ assert.equal(b, speed.max(a, b))
+ assert.equal(a, speed.min(a, b))
+ end)
+ it("should handle -1", function()
+ assert.is_false(speed.lessp(-1, math.random()))
+ end)
+ it("should handle nil", function()
+ assert.is_false(speed.greaterp(nil, math.random()))
+ end)
+ it("should handle mixed nil and -1", function()
+ assert.is_true(speed.equalp(nil, -1))
+ end)
+end)
+
+describe("The speed restriction setter", function()
+ it("should set the signal aspect", function()
+ local t = {speed_restrictions_t = {x = 5, y = 9}}
+ local u = {speed_restrictions_t = {x = 7, y = 9}, speed_restriction = 7}
+ speed.merge_aspect(t, {main = 7, type = "x"})
+ assert.same(u, t)
+ end)
+ it("should work with existing signal aspect tables", function()
+ local t = {speed_restrictions_t = {main = 5, foo = 3}}
+ local u = {speed_restrictions_t = {main = 7, foo = 3}, speed_restriction = 3}
+ speed.merge_aspect(t, {main = 7})
+ assert.same(u, t)
+ end)
+ it("should work with distant signals", function()
+ local t = {speed_restrictions_t = {main = 5}}
+ local u = {speed_restrictions_t = {main = 5}, speed_restriction = 5}
+ speed.merge_aspect(t, {})
+ assert.same(u, t)
+ end)
+ it("should create the restriction table if necessary", function()
+ local t = {speed_restriction = 5}
+ local u = {speed_restriction = 3, speed_restrictions_t = {main = 5, foo = 3}}
+ speed.merge_aspect(t, {main = 3, type = "foo"})
+ assert.same(u, t)
+ end)
+ it("should also create the restriction table for trains without any speed limit", function()
+ local t = {}
+ local u = {speed_restrictions_t = {}}
+ speed.merge_aspect(t, {})
+ assert.same(u, t)
+ end)
+ it("should set the speed restriction to nil if that is the case", function()
+ local t = {speed_restriction = math.random(20)}
+ local u = {speed_restrictions_t = {main = -1}}
+ speed.merge_aspect(t, {main = -1})
+ assert.same(u, t)
+ end)
+end)
diff --git a/advtrains/speed.lua b/advtrains/speed.lua
new file mode 100644
index 0000000..ec4f928
--- /dev/null
+++ b/advtrains/speed.lua
@@ -0,0 +1,88 @@
+-- auxiliary functions for the reworked speed restriction system
+
+local function s_lessp(a, b)
+ if not a or a == -1 then
+ return false
+ elseif not b or b == -1 then
+ return true
+ else
+ return a < b
+ end
+end
+
+local function s_greaterp(a, b)
+ return s_lessp(b, a)
+end
+
+local function s_not_lessp(a, b)
+ return not s_lessp(a, b)
+end
+
+local function s_not_greaterp(a, b)
+ return not s_greaterp(a, b)
+end
+
+local function s_equalp(a, b)
+ return (a or -1) == (b or -1)
+end
+
+local function s_not_equalp(a, b)
+ return (a or -1) ~= (b or -1)
+end
+
+local function s_max(a, b)
+ if s_lessp(a, b) then
+ return b
+ else
+ return a
+ end
+end
+
+local function s_min(a, b)
+ if s_lessp(a, b) then
+ return a
+ else
+ return b
+ end
+end
+
+local function get_speed_restriction_from_table (tbl)
+ local strictest = -1
+ for _, v in pairs(tbl) do
+ strictest = s_min(strictest, v)
+ end
+ if strictest == -1 then
+ return nil
+ end
+ return strictest
+end
+
+local function set_speed_restriction (tbl, rtype, rval)
+ if rval then
+ tbl[rtype or "main"] = rval
+ end
+ return tbl
+end
+
+local function set_speed_restriction_for_train (train, rtype, rval)
+ local t = train.speed_restrictions_t or {main = train.speed_restriction}
+ train.speed_restrictions_t = set_speed_restriction(t, rtype, rval)
+ train.speed_restriction = get_speed_restriction_from_table(t)
+end
+
+local function merge_speed_restriction_from_aspect_to_train (train, asp)
+ return set_speed_restriction_for_train(train, asp.type, asp.main)
+end
+
+return {
+ lessp = s_lessp,
+ greaterp = s_greaterp,
+ not_lessp = s_not_lessp,
+ not_greaterp = s_not_greaterp,
+ equalp = s_equalp,
+ not_equalp = s_not_equalp,
+ max = s_max,
+ min = s_min,
+ set_restriction = set_speed_restriction_for_train,
+ merge_aspect = merge_speed_restriction_from_aspect_to_train,
+}
diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua
index e7f2fd4..10af567 100644
--- a/advtrains/trainlogic.lua
+++ b/advtrains/trainlogic.lua
@@ -1168,6 +1168,7 @@ function advtrains.split_train_at_index(train, index)
newtrain.line = train.line
newtrain.routingcode = train.routingcode
newtrain.speed_restriction = train.speed_restriction
+ newtrain.speed_restrictions_t = table.copy(train.speed_restrictions_t)
newtrain.is_shunt = train.is_shunt
newtrain.points_split = advtrains.merge_tables(train.points_split)
newtrain.autocouple = train.autocouple
@@ -1210,10 +1211,10 @@ function advtrains.invert_train(train_id)
-- 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
train.is_shunt = true
- train.speed_restriction = advtrains.SHUNT_SPEED_MAX
+ advtrains.speed.set_restriction(train, "main", advtrains.SHUNT_SPEED_MAX)
else
train.is_shunt = false
- train.speed_restriction = nil
+ advtrains.speed.set_restriction(train, "main", -1)
end
end
diff --git a/advtrains_interlocking/approach.lua b/advtrains_interlocking/approach.lua
index f60468a..eecf09a 100644
--- a/advtrains_interlocking/approach.lua
+++ b/advtrains_interlocking/approach.lua
@@ -14,19 +14,19 @@ local SHUNT_SPEED_MAX = advtrains.SHUNT_SPEED_MAX
local il = advtrains.interlocking
-local function get_over_function(speed, shunt)
+local function get_over_function(speed, shunt, asptype)
return function(pos, id, train, index, speed, lzbdata)
if speed == 0 and minetest.settings:get_bool("at_il_force_lzb_halt") then
atwarn(id,"overrun LZB 0 restriction (red signal) ",pos)
-- Set train 1 index backward. Hope this does not lead to bugs...
--train.index = index - 0.5
- train.speed_restriction = 0
+ advtrains.speed.set_restriction(train, "main", 0)
--TODO temporary
--advtrains.drb_dump(id)
--error("Debug: "..id.." triggered LZB-0")
else
- train.speed_restriction = speed
+ advtrains.speed.set_restriction(train, asptype, speed or -1)
train.is_shunt = shunt
end
--atdebug("train drove over IP: speed=",speed,"shunt=",shunt)
@@ -94,6 +94,7 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered,
end
-- nspd can now be: 1. !=0: new speed restriction, 2. =0: stop here or 3. nil: keep travspd
if nspd then
+ travspd = nspd
if nspd == -1 then
travspd = nil
else
@@ -106,7 +107,7 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered,
lspd = travspd
local udata = {signal_pos = spos}
- local callback = get_over_function(lspd, travsht)
+ local callback = get_over_function(lspd, travsht, asp.type)
lzbdata.il_shunt = travsht
lzbdata.il_speed = travspd
--atdebug("new lzbdata",lzbdata)
diff --git a/advtrains_signals_ks/doc/advtrains_signals_ks.7advtrains.md b/advtrains_signals_ks/doc/advtrains_signals_ks.7advtrains.md
new file mode 100644
index 0000000..a043343
--- /dev/null
+++ b/advtrains_signals_ks/doc/advtrains_signals_ks.7advtrains.md
@@ -0,0 +1,60 @@
+% advtrains_signals_ks(7advtrains) | Advtrains User Guide
+
+# NAME
+`advtrains_signals_ks` - Ks signals for advtrains
+
+# DESCRIPTION
+
+This mod includes a modified subset of German rail signals. This page documents the signals implemented by this mod and some differences between this mod and German signals used in real life. The TODO section is currently included as there are notable modifications to this mod by the current `new-ks` branch, but it will be removed when the branch is ready for review.
+
+# SIGNAL ASPECTS
+
+This section mainly describes the different signal aspects. Please note that the meaning of some signal aspects may differ from their RL counterparts, and that the differences documented in the following section are not comprehensive.
+
+Due to historical reasons, "ex-DB" and "ex-DR" are used to refer to the former Deutsche Bundesbahn (West Germany) and the former Deutsche Reichsbahn (East Germany), respectively.
+
+## Ks signals
+The Ks signals are used like most other signals in advtrains. It has the following aspects:
+
+* Hp 0 (red light): Stop
+* Ks 1 (green light): Proceed at maximum speed or with the speed limit shown on the Zs 3 indicator directly above the signal (if present) and expect to proceed the next main signal at maximum speed or, if the green light is flashing, with the speed limit shown on the Zs 3v indicator directly below the signal
+* Ks 2 (yellow light): Proceed at maximum speed or with the speed limit shown on the Zs 3 indicator directly above the signal (if present) and expect to stop in front of the next main signal.
+
+In addition, Sh 1 (see below) may also appear with Hp 0, in which case the train continues in shunt mode.
+
+## Shunt signals
+Shunt signals are labeled "Ks Shunting signal" in-game. It has the following aspects:
+
+* Sh 0 (two horizontally aligned red lights): Stop
+* Sh 1/(ex-DR) Ra 12 (two white lights aligned on a slanted line): shunting allowed
+
+## Signal signs
+There are a few signal signs provided by this mod:
+
+* Lf 7 (black number on a white background): Proceed with the permanent speed limit shown on the sign
+* Lf 1/2 (black number on a yellow background): Proceed with the temporary speed limit shown on the sign
+* Lf 3 (black letter "E" on a yellow background): The temporary speed limit previously set by Lf 1/2 is lifted
+* "E" signal (**not** Lf 3) (black letter "E" on a white background): Proceed at maximum speed
+* Ra 10 (the black text "Halt für Rangierfahrten" on a white semicircle): Do not proceed if in shunt mode
+* Proceed as main ("PAM", in-game only) ("S" below a green arrow): Proceed without shunt mode
+
+# DIFFERENCES FROM REAL-LIFE SIGNALS
+
+[This document](https://www.bahnstatistik.de/Signale_pdf/SB-DBAG.pdf) is used for reference,
+
+* The speed is indicated in m/s instead of multiples of 10km/h.
+* Due to the potentially large number of nodes, only certain hard-coded values are allowed.
+* Certain visual effects, such as making signal signs reflective or lit at night, are not implemented.
+* The "E" sign, unlike Lf 3, lifts the main speed restriction as if by Hp 1.
+* The actual Lf 3 has an orange background.
+* Signal signs operate independently from other signals.
+* Distant signaling is not yet implemented.
+* The location of most signals are not checked. The location of Zs 3 and Zs 3v are only checked relative to the location of the main (Ks) signal.
+* The "shunt signals" in this mod are actually known as "Schutzsignale". The word "Rangiersignale" refers to a different set of signals (including acoustic signals) given by the person specifically responsible for train shunting.
+* The ex-DB definition of Sh 1 ("Fahrverbot aufgehoben") is that the track section ahead is clear and does not imply that the driver is allowed to proceed.
+* @orwell noted on the Minetest forum that the function of Lf 7 in the mod should normally be done with Zs 3.
+
+# TODO
+* Implement warning speed for temporary slow zones ("vorübergehende Langsamfahrstellen") with Lf 1/Lf 2 and Lf 3.
+* Use Zs 3 instead of Lf 7 for the main speed restriction; use Lf 7 for line speed restriction.
+* Change the "E" sign to Zs 10.
diff --git a/advtrains_signals_ks/init.lua b/advtrains_signals_ks/init.lua
index 3a2f4d0..14d27b8 100755
--- a/advtrains_signals_ks/init.lua
+++ b/advtrains_signals_ks/init.lua
@@ -116,6 +116,7 @@ local suppasp_ra = {
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:hs")
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:ra")
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:sign")
+advtrains.trackplacer.register_tracktype("advtrains_signals_ks:sign_lf")
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:zs3")
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:zs3v")
advtrains.trackplacer.register_tracktype("advtrains_signals_ks:mast")
@@ -296,6 +297,47 @@ for _, rtab in ipairs({
-- rotatable by trackworker
advtrains.trackplacer.add_worked("advtrains_signals_ks:sign", typ, "_"..rot, prts.n)
end
+
+ for typ, prts in pairs {
+ [8] = {main = 8, n = "12", ici = true},
+ [12] = {main = 12, n = "16"},
+ [16] = {main = 16, n = "e"},
+ ["e"] = {main = -1, n = "8"}
+ } do
+ minetest.register_node("advtrains_signals_ks:sign_lf_"..typ.."_"..rot, {
+ description = "Temporary local speed restriction sign",
+ drawtype = "mesh",
+ mesh = "advtrains_signals_ks_sign_smr"..rot..".obj",
+ tiles = {"advtrains_signals_ks_signpost.png", "advtrains_signals_ks_sign_"..typ..".png^[multiply:orange"},
+ paramtype = "light",
+ sunlight_propagates = true,
+ light_source = 4,
+ paramtype2 = "facedir",
+ selection_box = {
+ type = "fixed",
+ fixed = {rtab.sbox, {-1/4, -1/2, -1/4, 1/4, -7/16, 1/4}}
+ },
+ groups = {
+ cracky = 2,
+ advtrains_signal = 2,
+ not_blocking_trains = 1,
+ save_in_at_nodedb = 1,
+ not_in_creative_inventory = (rtab.ici and prts.ici) and 0 or 1,
+ },
+ drop = "advtrains_signals_ks:sign_lf_8_0",
+ inventory_image = "advtrains_signals_ks_sign_8.png^[multiply:orange",
+ advtrains = {
+ -- This is a static signal! No set_aspect
+ get_aspect = function(pos, node)
+ return {main = prts.main, type = "temp"}
+ end,
+ },
+ on_rightclick = advtrains.interlocking.signal_rc_handler,
+ can_dig = advtrains.interlocking.signal_can_dig,
+ after_dig_node = advtrains.interlocking.signal_after_dig
+ })
+ advtrains.trackplacer.add_worked("advtrains_signals_ks:sign_lf", tostring(typ), "_"..rot, prts.n)
+ end
-- Geschwindigkeits(vor)anzeiger für Ks-Signale
for typ, prts in pairs({