diff --git a/advtrains/stop_on_inactivity.lua b/advtrains/stop_on_inactivity.lua
new file mode 100644
index 0000000000000000000000000000000000000000..8d6addd1503b38ebf8e6133a198a0a976560f95a
--- /dev/null
+++ b/advtrains/stop_on_inactivity.lua
@@ -0,0 +1,61 @@
+local DISABLE_TIMEOUT = tonumber(minetest.settings:get("kif_custom.advtrains.disable_timeout")) or 60 * 60
+
+local trains_disabled = #minetest.get_connected_players == 0
+local disable_job = nil
+
+
+minetest.register_on_joinplayer(function(player, last_login)
+	-- activate trains
+	if disable_job ~= nil then
+		disable_job:cancel()
+		disable_job = nil
+	end
+	if trains_disabled then
+		trains_disabled = false
+	end
+end)
+
+minetest.register_on_leaveplayer(function(player, timed_out)
+	if #minetest.get_connected_players() == 0 then
+		-- deactivate trains
+		if disable_job == nil then
+			disable_job = minetest.after(DISABLE_TIMEOUT, function()
+				trains_disabled = true
+				disable_job = nil
+			end)
+		end
+	end
+end)
+
+
+-- overrides
+
+assert(type(advtrains.train_ensure_init) == "function")
+local old_train_ensure_init = advtrains.train_ensure_init
+advtrains.train_ensure_init = function(k, v)
+	if trains_disabled then
+		return
+	else
+		return old_train_ensure_init(k, v)
+	end
+end
+
+assert(type(advtrains.train_step_b) == "function")
+local old_train_step_b = advtrains.train_step_b
+advtrains.train_step_b = function(k, v, dtime)
+	if trains_disabled then
+		return
+	else
+		return old_train_step_b(k, v, dtime)
+	end
+end
+
+assert(type(advtrains.train_step_c) == "function")
+local old_train_step_c = advtrains.train_step_c
+advtrains.train_step_c = function(k, v, dtime)
+	if trains_disabled then
+		return
+	else
+		return old_train_step_c(k, v, dtime)
+	end
+end
diff --git a/settingtypes.txt b/settingtypes.txt
index 84ca5f47fa1b95e20fa5822ad8508659297ae462..4360a3feaecb6dde91dab93fcf2174cbda13b7af 100644
--- a/settingtypes.txt
+++ b/settingtypes.txt
@@ -13,3 +13,8 @@ kif_custom.death.waypoint_expires_seconds_creative (Seconds in which waypoints e
 # until it disappears, but also changes to a blue, green and finally red tint before disappearing.
 # The saturation interpolates between the color and the grey shade of the same value.
 kif_custom.death.waypoint_saturation (Color saturation) float 1 0 2
+
+[advtrains]
+
+# The amount of seconds until all trains are stopped after the last player has left.
+kif_custom.advtrains.disable_timeout (Disable timeout) int 3600 0 604800