Redesign formspec; add display/LN/RC edit boxes

master
yw05 2021-06-19 11:04:06 +02:00
parent 024b6fed8f
commit f0b8b44a7f
4 changed files with 248 additions and 144 deletions

13
Makefile Normal file
View File

@ -0,0 +1,13 @@
# trivial makefile to generate init.lua
all: init.lua
%.lua: %.fnl
fennel --compile $< > $@
.PHONY: test clean
test: macrotest.fnl
fennel macrotest.fnl
clean:
-rm *.lua *~

View File

@ -38,13 +38,25 @@
(local fsheader "formspec_version[3]")
(local fstext-train "%s
size[11.5,6]
label[0.5,0.5;%s]
size[11.5,11]
label[0.5,0.75;%s]
label[0.5,1.25;%s]
button[6,0.5;5,1;update;%s]
label[0.5,1;%s]textlist[0.5,1.5;5,2.5;lever;%s,%s,%s,%s,%s;%d;false]
label[6,2;%s]textlist[6,2.5;5,1.5;door;%s,%s,%s;%d;false]
button[0.5,4.5;5,1;reverse;%s]
textlist[6,4.5;5,1;ars;%s,%s;%d;false]
label[1.25,2;%s]label[1.25,2.5;%s]label[1.25,3;%s]label[1.25,3.5;%s]label[1.25,4;%s]
scrollbaroptions[min=1;max=5;smallstep=1;largestep=1;thumbsize=1;arrows=hide]
scrollbar[0.5,1.75;0.5,2.5;vertical;lever;%d]
label[6,2;%s]scrollbaroptions[min=1;max=3;smallstep=1;largestep=1;thumbsize=1;arrows=hide]
scrollbar[8.5,1.75;2.5,0.5;horizontal;door;%d]
checkbox[6,2.75;ars;%s;%s]
button[6,3.25;5,1;reverse;%s]
field[0.5,5;9.5,1;outtext;%s;%s]
button[10,5;1,1;outset;%s]
field[0.5,6.5;9.5,1;intext;%s;%s]
button[10,6.5;1,1;inset;%s]
field[0.5,8;9.5,1;lntext;%s;%s]
button[10,8;1,1;lnset;%s]
field[0.5,9.5;9.5,1;rctext;%s;%s]
button[10,9.5;1,1;rcset;%s]
")
(fn fsformat [fmt ...]
@ -63,8 +75,8 @@ textlist[6,4.5;5,1;ars;%s,%s;%d;false]
(local fs# (fsformat ,fstext-train
,fsheader
["Remote control for @1" tid#]
["Wagon(s): @1" (length t#.trainparts)]
["Update"]
["Lever"]
["Accelerate"]
["Neutral"]
["Roll"]
@ -72,14 +84,22 @@ textlist[6,4.5;5,1;ars;%s,%s;%d;false]
["Emergency brake"]
(- 5 (leverof t#))
["Door control"]
["Open left"]
["Close both"]
["Open right"]
(+ (or t#.door_open 0) 2)
["Automatic routesetting"]
(if (and advtrains.interlocking t#.ars_disable) "false" "true")
["Reverse train"]
["Enable ARS"]
["Disable ARS"]
(or (and advtrains.interlocking t#.ars_disable 2) 1)))
["External display"]
(or t#.text_outside "")
["Set"]
["Internal display"]
(or t#.text_inside "")
["Set"]
["Line"]
(or t#.line "")
["Set"]
["Routing code"]
(or t#.routingcode "")
["Set"]))
(minetest.show_formspec pn# (.. "train_remote:t" tid#) fs#)))))
(fn get-textlist [field max]
@ -90,16 +110,27 @@ textlist[6,4.5;5,1;ars;%s,%s;%d;false]
et#.index
nil)))
(fn has-scrollbar-event [field]
`(let [et# (minetest.explode_scrollbar_event ,field)]
(if (not et#) false
(= et#.type :CHG))))
(fn get-scrollbar [field min max]
`(let [et# (minetest.explode_scrollbar_event ,field)]
(if (not et#) nil
(and (= et#.type :CHG) (>= et#.value ,min) (<= et#.value ,max)) et#.value
nil)))
(fn handle-train-control-fields [trainid pname fields]
`(let [trainid# ,trainid pname# ,pname fields# ,fields]
(if (not trainid#) nil
(not (check-train-access pname# trainid#)) nil
(let [t# (. advtrains.trains trainid#)]
(if fields#.door
(let [dside# (get-textlist fields#.door 3)]
(if (has-scrollbar-event fields#.door)
(let [dside# (get-scrollbar fields#.door 1 3)]
(if dside# (tset t# :door_open (- dside# 2))))
fields#.lever
(let [tlev# (get-textlist fields#.lever 5)]
(has-scrollbar-event fields#.lever)
(let [tlev# (get-scrollbar fields#.lever 1 5)]
(if tlev# (tset t# :ctrl_user (- 5 tlev#))))
fields#.reverse
(when (<= t#.velocity 0)
@ -107,8 +138,18 @@ textlist[6,4.5;5,1;ars;%s,%s;%d;false]
(advtrains.atc.train_reset_command t#))
fields#.ars
(if advtrains.interlocking
(let [e# (get-textlist fields.ars 2)]
(if e# (advtrains.interlocking.ars_set_disable t# (= e# 2))))))
(advtrains.interlocking.ars_set_disable
t# (not (minetest.is_yes fields#.ars)))))
(when fields#.outtext
(tset t# :text_outside fields#.outtext))
(when fields#.intext
(tset t# :text_inside fields#.intext))
(when fields#.lntext
(tset t# :line fields#.lntext)
(minetest.after 0 advtrains.invalidate_path trainid#))
(when fields#.rctext
(tset t# :routingcode fields#.rctext)
(minetest.after 0 advtrains.invalidate_path trainid#))
(show-train-remote-formspec pname# trainid#)
nil))))
@ -126,5 +167,7 @@ textlist[6,4.5;5,1;ars;%s,%s;%d;false]
: fsformat
: show-train-remote-formspec
: get-textlist
: has-scrollbar-event
: get-scrollbar
: handle-train-control-fields
: handle-wagon-control-fields}

294
init.lua
View File

@ -1,116 +1,26 @@
local fsversion = 3
local fstext_train = "\nsize[11.5,6]\nlabel[0.5,0.5;%s]\nbutton[6,0.5;5,1;update;%s]\nlabel[0.5,1;%s]textlist[0.5,1.5;5,2.5;lever;%s,%s,%s,%s,%s;%d;false]\nlabel[6,2;%s]textlist[6,2.5;5,1.5;door;%s,%s,%s;%d;false]\nbutton[0.5,4.5;5,1;reverse;%s]\ntextlist[6,4.5;5,1;ars;%s,%s;%d;false]\n"
local function _0_(player, formname, fields)
local pname = player:get_player_name()
local trainid = string.match(formname, "^train_remote:(%S+)$")
if not trainid then
return nil
else
local _1_
do
local pn_0_ = pname
local tid_0_ = trainid
if not minetest.get_player_by_name(pn_0_) then
minetest.translate("train_remote", "Player is not online")
_1_ = false
else
local t_0_ = advtrains.trains[tid_0_]
if not t_0_ then
minetest.translate("train_remote", "No train with ID @1", tid_0_)
_1_ = false
else
local tps_0_ = t_0_.trainparts
local n_0_ = #tps_0_
local wagons_0_ = advtrains.wagons
local i_0_ = 0
local contp_0_ = true
while ((i_0_ <= n_0_) and contp_0_) do
local w_0_ = (wagons_0_)[(tps_0_)[i_0_]]
local function _4_()
local w_0_0 = w_0_
return advtrains.check_driving_couple_protection(pname, w_0_0.owner, w_0_0.whitelist)
end
if (w_0_ and _4_()) then
contp_0_ = false
else
i_0_ = (1 + i_0_)
end
end
_1_ = not contp_0_
end
end
end
if not _1_ then
local trainid = string.match(formname, "^train_remote:t(%S+)$")
local wagonid = string.match(formname, "^train_remote:w(%S+)$")
if trainid then
local trainid_0_ = trainid
local pname_0_ = pname
local fields_0_ = fields
if not trainid_0_ then
return nil
else
local t = advtrains.trains[trainid]
if fields.door then
local dside
do
local et_0_ = minetest.explode_textlist_event(fields.door)
if not et_0_ then
dside = nil
elseif (((et_0_.type == "CHG") or (et_0_.type == "DCL")) and (et_0_.index >= 1) and (et_0_.index <= 3)) then
dside = et_0_.index
else
dside = nil
end
end
if dside then
t["door_open"] = (dside - 2)
end
elseif fields.lever then
local tlev
do
local et_0_ = minetest.explode_textlist_event(fields.lever)
if not et_0_ then
tlev = nil
elseif (((et_0_.type == "CHG") or (et_0_.type == "DCL")) and (et_0_.index >= 1) and (et_0_.index <= 5)) then
tlev = et_0_.index
else
tlev = nil
end
end
if (tlev and not t.lzb_effect_tmr) then
t["ctrl_user"] = (5 - tlev)
end
elseif fields.reverse then
if (t.velocity <= 0) then
advtrains.invert_train(trainid)
advtrains.atc.train_reset_command(t)
end
elseif fields.ars then
if advtrains.interlocking then
local e
do
local et_0_ = minetest.explode_textlist_event(fields.ars)
if not et_0_ then
e = nil
elseif (((et_0_.type == "CHG") or (et_0_.type == "DCL")) and (et_0_.index >= 1) and (et_0_.index <= 2)) then
e = et_0_.index
else
e = nil
end
end
if e then
advtrains.interlocking.ars_set_disable(t, (e == 2))
end
end
end
local pn_0_ = pname
local tid_0_ = trainid
local _3_
local _1_
do
local pn_0_0 = pn_0_
local tid_0_0 = tid_0_
if not minetest.get_player_by_name(pn_0_0) then
local pn_0_ = pname_0_
local tid_0_ = trainid_0_
if not minetest.get_player_by_name(pn_0_) then
minetest.translate("train_remote", "Player is not online")
_3_ = false
_1_ = false
else
local t_0_ = advtrains.trains[tid_0_0]
local t_0_ = advtrains.trains[tid_0_]
if not t_0_ then
minetest.translate("train_remote", "No train with ID @1", tid_0_0)
_3_ = false
minetest.translate("train_remote", "No train with ID @1", tid_0_)
_1_ = false
else
local tps_0_ = t_0_.trainparts
local n_0_ = #tps_0_
@ -119,41 +29,171 @@ local function _0_(player, formname, fields)
local contp_0_ = true
while ((i_0_ <= n_0_) and contp_0_) do
local w_0_ = (wagons_0_)[(tps_0_)[i_0_]]
local function _6_()
local function _4_()
local w_0_0 = w_0_
return advtrains.check_driving_couple_protection(pname, w_0_0.owner, w_0_0.whitelist)
end
if (w_0_ and _6_()) then
if (w_0_ and _4_()) then
contp_0_ = false
else
i_0_ = (1 + i_0_)
end
end
_3_ = not contp_0_
_1_ = not contp_0_
end
end
end
if not _3_ then
if not _1_ then
return nil
else
local t_0_ = advtrains.trains[tid_0_]
local fs_0_
local function _4_()
local t_0_0 = t_0_
if not t_0_0 then
return nil
elseif ((t_0_0.velocity == 0) and not t_0_0.active_control) then
return 1
elseif t_0_0.hud_lzb_effect_tmr then
return 1
local t_0_ = advtrains.trains[trainid_0_]
local _2_
do
local et_0_ = minetest.explode_scrollbar_event(fields_0_.door)
if not et_0_ then
_2_ = false
else
return (t_0_0.lever or 3)
_2_ = (et_0_.type == "CHG")
end
end
fs_0_ = string.format(fstext_train, minetest.formspec_escape(minetest.translate("train_remote", "Remote control for @1", tid_0_)), minetest.formspec_escape(minetest.translate("train_remote", "Update")), minetest.formspec_escape(minetest.translate("train_remote", "Lever")), minetest.formspec_escape(minetest.translate("train_remote", "Accelerate")), minetest.formspec_escape(minetest.translate("train_remote", "Neutral")), minetest.formspec_escape(minetest.translate("train_remote", "Roll")), minetest.formspec_escape(minetest.translate("train_remote", "Regular brake")), minetest.formspec_escape(minetest.translate("train_remote", "Emergency brake")), (5 - _4_()), minetest.formspec_escape(minetest.translate("train_remote", "Door control")), minetest.formspec_escape(minetest.translate("train_remote", "Open left")), minetest.formspec_escape(minetest.translate("train_remote", "Close both")), minetest.formspec_escape(minetest.translate("train_remote", "Open right")), ((t_0_.door_open or 0) + 2), minetest.formspec_escape(minetest.translate("train_remote", "Reverse train")), minetest.formspec_escape(minetest.translate("train_remote", "Enable ARS")), minetest.formspec_escape(minetest.translate("train_remote", "Disable ARS")), ((advtrains.interlocking and t_0_.ars_disable and 2) or 1))
return minetest.show_formspec(pn_0_, ("train_remote:" .. tid_0_), fs_0_)
if _2_ then
local dside_0_
do
local et_0_ = minetest.explode_scrollbar_event(fields_0_.door)
if not et_0_ then
dside_0_ = nil
elseif ((et_0_.type == "CHG") and (et_0_.value >= 1) and (et_0_.value <= 3)) then
dside_0_ = et_0_.value
else
dside_0_ = nil
end
end
if dside_0_ then
t_0_["door_open"] = (dside_0_ - 2)
end
else
local _3_
do
local et_0_ = minetest.explode_scrollbar_event(fields_0_.lever)
if not et_0_ then
_3_ = false
else
_3_ = (et_0_.type == "CHG")
end
end
if _3_ then
local tlev_0_
do
local et_0_ = minetest.explode_scrollbar_event(fields_0_.lever)
if not et_0_ then
tlev_0_ = nil
elseif ((et_0_.type == "CHG") and (et_0_.value >= 1) and (et_0_.value <= 5)) then
tlev_0_ = et_0_.value
else
tlev_0_ = nil
end
end
if tlev_0_ then
t_0_["ctrl_user"] = (5 - tlev_0_)
end
elseif fields_0_.reverse then
if (t_0_.velocity <= 0) then
advtrains.invert_train(trainid_0_)
advtrains.atc.train_reset_command(t_0_)
end
elseif fields_0_.ars then
if advtrains.interlocking then
advtrains.interlocking.ars_set_disable(t_0_, not minetest.is_yes(fields_0_.ars))
end
end
end
if fields_0_.outtext then
t_0_["text_outside"] = fields_0_.outtext
end
if fields_0_.intext then
t_0_["text_inside"] = fields_0_.intext
end
if fields_0_.lntext then
t_0_["line"] = fields_0_.lntext
minetest.after(0, advtrains.invalidate_path, trainid_0_)
end
if fields_0_.rctext then
t_0_["routingcode"] = fields_0_.rctext
minetest.after(0, advtrains.invalidate_path, trainid_0_)
end
do
local pn_0_ = pname_0_
local tid_0_ = trainid_0_
local _7_
do
local pn_0_0 = pn_0_
local tid_0_0 = tid_0_
if not minetest.get_player_by_name(pn_0_0) then
minetest.translate("train_remote", "Player is not online")
_7_ = false
else
local t_0_0 = advtrains.trains[tid_0_0]
if not t_0_0 then
minetest.translate("train_remote", "No train with ID @1", tid_0_0)
_7_ = false
else
local tps_0_ = t_0_0.trainparts
local n_0_ = #tps_0_
local wagons_0_ = advtrains.wagons
local i_0_ = 0
local contp_0_ = true
while ((i_0_ <= n_0_) and contp_0_) do
local w_0_ = (wagons_0_)[(tps_0_)[i_0_]]
local function _10_()
local w_0_0 = w_0_
return advtrains.check_driving_couple_protection(pname, w_0_0.owner, w_0_0.whitelist)
end
if (w_0_ and _10_()) then
contp_0_ = false
else
i_0_ = (1 + i_0_)
end
end
_7_ = not contp_0_
end
end
end
if not _7_ then
else
local t_0_0 = advtrains.trains[tid_0_]
local fs_0_
local function _8_()
local t_0_1 = t_0_0
if not t_0_1 then
return nil
elseif ((t_0_1.velocity == 0) and not t_0_1.active_control) then
return 1
elseif t_0_1.hud_lzb_effect_tmr then
return 1
else
return (t_0_1.lever or 3)
end
end
local _9_
if (advtrains.interlocking and t_0_0.ars_disable) then
_9_ = "false"
else
_9_ = "true"
end
fs_0_ = string.format("%s\nsize[11.5,11]\nlabel[0.5,0.75;%s]\nlabel[0.5,1.25;%s]\nbutton[6,0.5;5,1;update;%s]\nlabel[1.25,2;%s]label[1.25,2.5;%s]label[1.25,3;%s]label[1.25,3.5;%s]label[1.25,4;%s]\nscrollbaroptions[min=1;max=5;smallstep=1;largestep=1;thumbsize=1;arrows=hide]\nscrollbar[0.5,1.75;0.5,2.5;vertical;lever;%d]\nlabel[6,2;%s]scrollbaroptions[min=1;max=3;smallstep=1;largestep=1;thumbsize=1;arrows=hide]\nscrollbar[8.5,1.75;2.5,0.5;horizontal;door;%d]\ncheckbox[6,2.75;ars;%s;%s]\nbutton[6,3.25;5,1;reverse;%s]\nfield[0.5,5;9.5,1;outtext;%s;%s]\nbutton[10,5;1,1;outset;%s]\nfield[0.5,6.5;9.5,1;intext;%s;%s]\nbutton[10,6.5;1,1;inset;%s]\nfield[0.5,8;9.5,1;lntext;%s;%s]\nbutton[10,8;1,1;lnset;%s]\nfield[0.5,9.5;9.5,1;rctext;%s;%s]\nbutton[10,9.5;1,1;rcset;%s]\n", "formspec_version[3]", minetest.formspec_escape(minetest.translate("train_remote", "Remote control for @1", tid_0_)), minetest.formspec_escape(minetest.translate("train_remote", "Wagon(s): @1", #t_0_0.trainparts)), minetest.formspec_escape(minetest.translate("train_remote", "Update")), minetest.formspec_escape(minetest.translate("train_remote", "Accelerate")), minetest.formspec_escape(minetest.translate("train_remote", "Neutral")), minetest.formspec_escape(minetest.translate("train_remote", "Roll")), minetest.formspec_escape(minetest.translate("train_remote", "Regular brake")), minetest.formspec_escape(minetest.translate("train_remote", "Emergency brake")), (5 - _8_()), minetest.formspec_escape(minetest.translate("train_remote", "Door control")), ((t_0_0.door_open or 0) + 2), minetest.formspec_escape(minetest.translate("train_remote", "Automatic routesetting")), _9_, minetest.formspec_escape(minetest.translate("train_remote", "Reverse train")), minetest.formspec_escape(minetest.translate("train_remote", "External display")), (t_0_0.text_outside or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Internal display")), (t_0_0.text_inside or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Line")), (t_0_0.line or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Routing code")), (t_0_0.routingcode or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")))
minetest.show_formspec(pn_0_, ("train_remote:t" .. tid_0_), fs_0_)
end
end
return nil
end
end
elseif wagonid then
local wagonid_0_ = wagonid
local pname_0_ = pname
local fields_0_ = fields
return nil
else
return nil
end
end
minetest.register_on_player_receive_fields(_0_)
@ -246,8 +286,14 @@ local function _1_(pname, trainid)
return (t_0_0.lever or 3)
end
end
fs_0_ = string.format(fstext_train, minetest.formspec_escape(minetest.translate("train_remote", "Remote control for @1", tid_0_)), minetest.formspec_escape(minetest.translate("train_remote", "Update")), minetest.formspec_escape(minetest.translate("train_remote", "Lever")), minetest.formspec_escape(minetest.translate("train_remote", "Accelerate")), minetest.formspec_escape(minetest.translate("train_remote", "Neutral")), minetest.formspec_escape(minetest.translate("train_remote", "Roll")), minetest.formspec_escape(minetest.translate("train_remote", "Regular brake")), minetest.formspec_escape(minetest.translate("train_remote", "Emergency brake")), (5 - _3_()), minetest.formspec_escape(minetest.translate("train_remote", "Door control")), minetest.formspec_escape(minetest.translate("train_remote", "Open left")), minetest.formspec_escape(minetest.translate("train_remote", "Close both")), minetest.formspec_escape(minetest.translate("train_remote", "Open right")), ((t_0_.door_open or 0) + 2), minetest.formspec_escape(minetest.translate("train_remote", "Reverse train")), minetest.formspec_escape(minetest.translate("train_remote", "Enable ARS")), minetest.formspec_escape(minetest.translate("train_remote", "Disable ARS")), ((advtrains.interlocking and t_0_.ars_disable and 2) or 1))
minetest.show_formspec(pn_0_, ("train_remote:" .. tid_0_), fs_0_)
local _4_
if (advtrains.interlocking and t_0_.ars_disable) then
_4_ = "false"
else
_4_ = "true"
end
fs_0_ = string.format("%s\nsize[11.5,11]\nlabel[0.5,0.75;%s]\nlabel[0.5,1.25;%s]\nbutton[6,0.5;5,1;update;%s]\nlabel[1.25,2;%s]label[1.25,2.5;%s]label[1.25,3;%s]label[1.25,3.5;%s]label[1.25,4;%s]\nscrollbaroptions[min=1;max=5;smallstep=1;largestep=1;thumbsize=1;arrows=hide]\nscrollbar[0.5,1.75;0.5,2.5;vertical;lever;%d]\nlabel[6,2;%s]scrollbaroptions[min=1;max=3;smallstep=1;largestep=1;thumbsize=1;arrows=hide]\nscrollbar[8.5,1.75;2.5,0.5;horizontal;door;%d]\ncheckbox[6,2.75;ars;%s;%s]\nbutton[6,3.25;5,1;reverse;%s]\nfield[0.5,5;9.5,1;outtext;%s;%s]\nbutton[10,5;1,1;outset;%s]\nfield[0.5,6.5;9.5,1;intext;%s;%s]\nbutton[10,6.5;1,1;inset;%s]\nfield[0.5,8;9.5,1;lntext;%s;%s]\nbutton[10,8;1,1;lnset;%s]\nfield[0.5,9.5;9.5,1;rctext;%s;%s]\nbutton[10,9.5;1,1;rcset;%s]\n", "formspec_version[3]", minetest.formspec_escape(minetest.translate("train_remote", "Remote control for @1", tid_0_)), minetest.formspec_escape(minetest.translate("train_remote", "Wagon(s): @1", #t_0_.trainparts)), minetest.formspec_escape(minetest.translate("train_remote", "Update")), minetest.formspec_escape(minetest.translate("train_remote", "Accelerate")), minetest.formspec_escape(minetest.translate("train_remote", "Neutral")), minetest.formspec_escape(minetest.translate("train_remote", "Roll")), minetest.formspec_escape(minetest.translate("train_remote", "Regular brake")), minetest.formspec_escape(minetest.translate("train_remote", "Emergency brake")), (5 - _3_()), minetest.formspec_escape(minetest.translate("train_remote", "Door control")), ((t_0_.door_open or 0) + 2), minetest.formspec_escape(minetest.translate("train_remote", "Automatic routesetting")), _4_, minetest.formspec_escape(minetest.translate("train_remote", "Reverse train")), minetest.formspec_escape(minetest.translate("train_remote", "External display")), (t_0_.text_outside or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Internal display")), (t_0_.text_inside or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Line")), (t_0_.line or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")), minetest.formspec_escape(minetest.translate("train_remote", "Routing code")), (t_0_.routingcode or ""), minetest.formspec_escape(minetest.translate("train_remote", "Set")))
minetest.show_formspec(pn_0_, ("train_remote:t" .. tid_0_), fs_0_)
end
end
return nil

View File

@ -18,6 +18,8 @@
(expand (show-train-remote-formspec {:id "123456"} "Player"))
(expand (get-textlist {:type :CHG :index 5} 10))
(expand (get-textlist "event" 10))
(expand (has-scrollbar-event "event"))
(expand (get-scrollbar "event" 1 5))
(expand (handle-train-control-fields "123456" "Player" {}))