Compare commits

..

No commits in common. "45e5ad3b378b17be7e0ce314ba964e01792d673d" and "4cfd07e992ae44ac9d06c4936df9dc8d71ac905b" have entirely different histories.

7 changed files with 96 additions and 312 deletions

View File

@ -11,6 +11,12 @@ sources :
tasks:
- download_mt_server: |
mkdir bin
wget https://lifomaps.de/advtrains-test/builtin.tar.gz
tar xf builtin.tar.gz
curl https://lifomaps.de/advtrains-test/minetestserver -o ~/bin/minetestserver
chmod +x ~/bin/minetestserver
- install_mt_game : |
curl -L https://github.com/minetest/minetest_game/archive/master.zip -o master.zip
mkdir -p .minetest/games/
@ -39,4 +45,4 @@ tasks:
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
~/bin/minetestserver --port 31111 --gameid minetest_game --config ~/minetest.conf --world ~/.minetest/worlds/advtrains_testworld

View File

@ -202,7 +202,6 @@ advtrains.meseconrules =
advtrains.fpath=minetest.get_worldpath().."/advtrains"
advtrains.speed = dofile(advtrains.modpath.."/speed.lua")
advtrains.texture = dofile(advtrains.modpath.."/texture.lua")
dofile(advtrains.modpath.."/path.lua")
dofile(advtrains.modpath.."/trainlogic.lua")
@ -738,21 +737,6 @@ 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>",

View File

@ -74,5 +74,4 @@ Buffer and Chain Coupler=Schraubenkupplung
Scharfenberg Coupler=Scharfenbergkupplung
Japanese Train Inter-Wagon Connection=Waggonzwischenverbindung Japanischer Personenzug
Can not couple: The couplers of the trains do not match (@1 and @2).=Kann nicht ankuppeln: Die Kupplungen der Züge passen nicht zueinander (@1 und @2)
Train ID=Zugnummer
<none>=<keine>

View File

@ -1,19 +0,0 @@
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

@ -1,228 +0,0 @@
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

View File

@ -1,7 +1,5 @@
--trainhud.lua: holds all the code for train controlling
local T = advtrains.texture
advtrains.hud = {}
advtrains.hhud = {}
@ -186,94 +184,138 @@ 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 3
local tlev=train.lever or 1
if train.velocity==0 and not train.active_control then tlev=1 end
if train.hud_lzb_effect_tmr then
tlev=1
end
local hud = T.combine(440, 110, "black")
local ht = {"[combine:440x110:0,0=(advtrains_hud_bg.png^[resize\\:440x110)"}
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
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")
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)
-- reverser
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")
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)
-- train control/safety indication
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"))
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
-- door
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")
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)"
-- speed indication(s)
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")
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
if res and res > 0 then
hud:add_fill(7+res*11, 60, 3, 30, "red")
ht[#ht+1] = sformat("%d,60=(advtrains_hud_bg.png^[resize\\:3x30^[colorize\\:red\\:255)", 7+res*11)
end
if train.tarvelocity then
hud:add(1+train.tarvelocity*11, 85, T"advtrains_hud_arrow.png":transform"FY":multiply"cyan")
ht[#ht+1] = sformat("%d,85=(advtrains_hud_arrow.png^[multiply\\:cyan^[transformFY^[makealpha\\:#000000)", 1+train.tarvelocity*11)
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
hud:add(1+spd*11, 50, T"advtrains_hud_arrow.png":multiply"red")
ht[#ht+1] = sformat("%d,50=(advtrains_hud_arrow.png^[multiply\\:red^[makealpha\\:#000000)", 1+spd*11)
end
local dist = math.floor(((oc[i].index or train.index)-train.index))
local floor = math.floor
local dist = floor(((oc[i].index or train.index)-train.index))
dist = math.max(0, math.min(999, dist))
lzbdisp = {c = c, d = dist}
for j = 1, 3, 1 do
sevenseg(floor((dist/10^(3-j))%10), 119+j*11, 18, 4, 2, "[colorize\\:"..c)
end
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
table.insert(st, attrans("OVERRUN RED SIGNAL! Examine situation and reverse train to move again."))
st[#st+1] = attrans("OVERRUN RED SIGNAL! Examine situation and reverse train to move again.")
end
if train.atc_command then
table.insert(st, ("ATC: %s%s"):format(train.atc_delay and advtrains.abs_ceil(train.atc_delay).."s " or "", train.atc_command or ""))
st[#st+1] = sformat("ATC: %s%s", train.atc_delay and advtrains.abs_ceil(train.atc_delay).."s " or "", train.atc_command or "")
end
return table.concat(st,"\n"), tostring(hud)
return table.concat(st,"\n"), table.concat(ht,":")
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 = {checkpoints = {{speed=6, index=125.7}}}, index = 100,
door_open = 1, lzb = {oncoming = {{spd=6, idx=125.7}}}, index = 0,
}
minetest.register_node("advtrains:hud_demo",{

View File

@ -970,7 +970,7 @@ function wagon:show_bordcom(pname)
local data = advtrains.wagons[self.id]
local linhei
local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1 | "..attrans("Train ID")..": "..(minetest.formspec_escape(train.id or "")).."]"
local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1]"
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 "")).."]"