Simplify Signal Aspect Table (H#132) [breaks compatibility with signal API]
This commit is contained in:
parent
573d6b06b2
commit
119a09b784
@ -12,18 +12,10 @@ end
|
||||
|
||||
local function aspect(b)
|
||||
return {
|
||||
main = {
|
||||
free = b,
|
||||
speed = -1,
|
||||
},
|
||||
shunt = {
|
||||
free = false,
|
||||
proceed_as_main = true
|
||||
},
|
||||
dst = {
|
||||
free = true,
|
||||
speed = -1,
|
||||
},
|
||||
main = (not b) and 0, -- b ? false : 0
|
||||
shunt = false,
|
||||
proceed_as_main = true,
|
||||
dst = false,
|
||||
info = {}
|
||||
}
|
||||
end
|
||||
@ -81,7 +73,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
-- new signal API
|
||||
advtrains = {
|
||||
set_aspect = function(pos, node, asp)
|
||||
if asp.main.free then
|
||||
if asp.main != 0 then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_on"..rotation, param2 = node.param2}, true)
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_off"..rotation, param2 = node.param2}, true)
|
||||
@ -140,7 +132,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
-- new signal API
|
||||
advtrains = {
|
||||
set_aspect = function(pos, node, asp)
|
||||
if asp.main.free then
|
||||
if asp.main != 0 then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_on"..rotation, param2 = node.param2}, true)
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_off"..rotation, param2 = node.param2}, true)
|
||||
@ -208,7 +200,7 @@ for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red",
|
||||
-- new signal API
|
||||
advtrains = {
|
||||
set_aspect = function(pos, node, asp)
|
||||
if asp.main.free then
|
||||
if asp.main != 0 then
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_on", param2 = node.param2}, true)
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_off", param2 = node.param2}, true)
|
||||
|
@ -73,17 +73,17 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered,
|
||||
--interpreting aspect and determining speed to proceed
|
||||
if travsht then
|
||||
--shunt move
|
||||
if asp.shunt.free then
|
||||
if asp.shunt then
|
||||
nspd = SHUNT_SPEED_MAX
|
||||
elseif asp.shunt.proceed_as_main and asp.main.free then
|
||||
nspd = asp.main.speed
|
||||
elseif asp.shunt.proceed_as_main and asp.main != 0 then
|
||||
nspd = asp.main
|
||||
travsht = false
|
||||
end
|
||||
else
|
||||
--train move
|
||||
if asp.main.free then
|
||||
nspd = asp.main.speed
|
||||
elseif asp.shunt.free then
|
||||
if asp.main != 0 then
|
||||
nspd = asp.main
|
||||
elseif asp.shunt then
|
||||
nspd = SHUNT_SPEED_MAX
|
||||
travsht = true
|
||||
end
|
||||
|
@ -6,10 +6,10 @@
|
||||
|
||||
|
||||
local setaspect = function(pos, node, asp)
|
||||
if not asp.main.free then
|
||||
if asp.main == 0 then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_interlocking:ds_danger"})
|
||||
else
|
||||
if asp.dst.free and asp.main.speed == -1 then
|
||||
if asp.dst != 0 and asp.main == -1 then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_interlocking:ds_free"})
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_interlocking:ds_slow"})
|
||||
@ -22,18 +22,10 @@ local setaspect = function(pos, node, asp)
|
||||
end
|
||||
|
||||
local suppasp = {
|
||||
main = {
|
||||
free = nil,
|
||||
speed = {6, -1},
|
||||
},
|
||||
dst = {
|
||||
free = nil,
|
||||
speed = nil,
|
||||
},
|
||||
shunt = {
|
||||
free = false,
|
||||
main = {0, 6, -1},
|
||||
dst = {0, false},
|
||||
shunt = false,
|
||||
proceed_as_main = true,
|
||||
},
|
||||
info = {
|
||||
call_on = false,
|
||||
dead_end = false,
|
||||
@ -74,10 +66,7 @@ minetest.register_node("advtrains_interlocking:ds_free", {
|
||||
supported_aspects = suppasp,
|
||||
get_aspect = function(pos, node)
|
||||
return {
|
||||
main = {
|
||||
free = true,
|
||||
speed = -1,
|
||||
}
|
||||
main = -1,
|
||||
}
|
||||
end,
|
||||
},
|
||||
@ -98,10 +87,7 @@ minetest.register_node("advtrains_interlocking:ds_slow", {
|
||||
supported_aspects = suppasp,
|
||||
get_aspect = function(pos, node)
|
||||
return {
|
||||
main = {
|
||||
free = true,
|
||||
speed = 6,
|
||||
}
|
||||
main = 6,
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
@ -7,17 +7,9 @@ local function sigd_to_string(sigd)
|
||||
end
|
||||
|
||||
local asp_generic_free = {
|
||||
main = {
|
||||
free = true,
|
||||
speed = -1,
|
||||
},
|
||||
shunt = {
|
||||
free = false,
|
||||
},
|
||||
dst = {
|
||||
free = true,
|
||||
speed = -1,
|
||||
},
|
||||
main = -1,
|
||||
shunt = false,
|
||||
dst = false,
|
||||
info = {}
|
||||
}
|
||||
|
||||
|
@ -4,28 +4,38 @@
|
||||
--[[
|
||||
Signal aspect table:
|
||||
asp = {
|
||||
main = {
|
||||
free = <boolean>,
|
||||
speed = <int km/h>,
|
||||
},
|
||||
shunt = {
|
||||
free = <boolean>,
|
||||
main = <int speed>,
|
||||
-- Main signal aspect, tells state and permitted speed of next section
|
||||
-- 0 = section is blocked
|
||||
-- >0 = section is free, speed limit is this value
|
||||
-- -1 = section is free, maximum speed permitted
|
||||
-- false = Signal doesn't provide main signal information, retain current speed limit.
|
||||
shunt = <boolean>,
|
||||
-- Whether train may proceed as shunt move, on sight
|
||||
-- main aspect takes precedence over this
|
||||
-- When main==0, train switches to shunt move and is restricted to speed 8
|
||||
proceed_as_main = <boolean>,
|
||||
-- If an approaching train is a shunt move and "main.free" is set,
|
||||
-- If an approaching train is a shunt move and 'shunt' is false,
|
||||
-- the train may proceed as a train move under the "main" aspect
|
||||
-- if the main aspect permits it (i.e. main!=0)
|
||||
-- If this is not set, shunt moves are NOT allowed to switch to
|
||||
-- a train move, and must stop even if "main.free" is set.
|
||||
-- a train move, and must stop even if "main" would permit passing.
|
||||
-- This is intended to be used for "Halt for shunt moves" signs.
|
||||
}
|
||||
dst = {
|
||||
free = <boolean>,
|
||||
speed = <int km/h>,
|
||||
}
|
||||
|
||||
dst = <int speed>,
|
||||
-- Distant signal aspect, tells state and permitted speed of the section after next section
|
||||
-- The character of these information is purely informational
|
||||
-- At this time, this field is not actively used
|
||||
-- 0 = section is blocked
|
||||
-- >0 = section is free, speed limit is this value
|
||||
-- -1 = section is free, maximum speed permitted
|
||||
-- false = Signal doesn't provide distant signal information.
|
||||
|
||||
info = {
|
||||
-- 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
|
||||
@ -33,12 +43,6 @@ asp = {
|
||||
-- (Example: german Langsamfahrstellen-Signale)
|
||||
}
|
||||
}
|
||||
-- For "speed" and "w_speed" fields, a value of -1 means that the
|
||||
-- restriction is lifted. If they are omitted, the value imposed at
|
||||
-- the last aspect received remains valid.
|
||||
-- The "dst" subtable can be completely omitted when no explicit dst
|
||||
-- aspect should be signalled to the train. In this case, the last
|
||||
-- signalled dst aspect remains valid.
|
||||
|
||||
== How signals actually work in here ==
|
||||
Each signal (in the advtrains universe) is some node that has at least the
|
||||
@ -87,22 +91,18 @@ advtrains = {
|
||||
false: always shows "blocked", unchangable
|
||||
true: always shows "free", unchangable
|
||||
-- Any of the "speed" fields should contain a list of possible values
|
||||
-- to be set as restriction. If omitted, this signal should never
|
||||
-- set the corresponding "speed" field in the aspect, which means
|
||||
-- that the previous speed limit stays valid
|
||||
-- to be set as restriction. If omitted, the value of the described
|
||||
-- field is always assumed to be false (no information)
|
||||
-- A speed of 0 means that the signal can show a "blocked" aspect
|
||||
-- (which is probably the case for most signals)
|
||||
-- If the signal can signal "no information" on one of the fields
|
||||
-- (thus false is an acceptable value), include false in the list
|
||||
-- If your signal can only display a single speed (may it be -1),
|
||||
-- always enclose that single value into a list. (such as {-1})
|
||||
main = {
|
||||
free = <boolean/nil>,
|
||||
speed = {<speed1>, ..., <speedn>} or nil,
|
||||
},
|
||||
dst = {
|
||||
free = <boolean/nil>,
|
||||
speed = {<speed1>, ..., <speedn>} or nil,
|
||||
},
|
||||
shunt = {
|
||||
free = <boolean/nil>,
|
||||
},
|
||||
main = {<speed1>, ..., <speedn>} or nil,
|
||||
dst = {<speed1>, ..., <speedn>} or nil,
|
||||
shunt = <boolean/nil>,
|
||||
|
||||
info = {
|
||||
call_on = <boolean/nil>,
|
||||
dead_end = <boolean/nil>,
|
||||
@ -110,28 +110,36 @@ advtrains = {
|
||||
}
|
||||
|
||||
},
|
||||
Example for supported_aspects:
|
||||
supported_aspects = {
|
||||
main = {0, 6, -1}, -- can show either "Section blocked", "Proceed at speed 6" or "Proceed at maximum speed"
|
||||
dst = {0, false}, -- can show only if next signal shows "blocked", no other information.
|
||||
shunt = false, -- shunting by this signal is never allowed.
|
||||
|
||||
info = {
|
||||
call_on = false,
|
||||
dead_end = false,
|
||||
w_speed = nil,
|
||||
} -- none of the information can be shown by the signal
|
||||
|
||||
},
|
||||
|
||||
get_aspect = function(pos, node)
|
||||
-- This function gets called by the train safety system. It
|
||||
should return the aspect that this signal actually displays,
|
||||
not preferably the input of set_aspect.
|
||||
-- For regular, full-featured light signals, they will probably
|
||||
honor all entries in the original aspect, however, e.g.
|
||||
simple shunt signals always return main.free=true regardless of
|
||||
simple shunt signals always return main=false regardless of
|
||||
the set_aspect input because they can not signal "Halt" to
|
||||
train moves.
|
||||
-- advtrains.interlocking.DANGER contains a default "all-danger" aspect.
|
||||
-- If your signal does not cover certain sub-tables of the aspect,
|
||||
the following reasonable defaults are automatically assumed:
|
||||
main = {
|
||||
free = true,
|
||||
}
|
||||
dst = {
|
||||
free = true,
|
||||
}
|
||||
shunt = {
|
||||
free = false,
|
||||
proceed_as_main = false,
|
||||
}
|
||||
main = false (unchanged)
|
||||
dst = false (unchanged)
|
||||
shunt = false (shunting not allowed)
|
||||
info = {} (no further information)
|
||||
end,
|
||||
}
|
||||
on_rightclick = advtrains.interlocking.signal_rc_handler
|
||||
@ -155,48 +163,14 @@ This function will query get_aspect to retrieve the new aspect.
|
||||
]]--
|
||||
|
||||
local DANGER = {
|
||||
main = {
|
||||
free = false,
|
||||
speed = 0,
|
||||
},
|
||||
shunt = {
|
||||
free = false,
|
||||
},
|
||||
dst = {
|
||||
free = false,
|
||||
speed = 0,
|
||||
},
|
||||
main = 0,
|
||||
dst = false,
|
||||
shunt = false,
|
||||
info = {}
|
||||
}
|
||||
advtrains.interlocking.DANGER = DANGER
|
||||
|
||||
local function fillout_aspect(asp)
|
||||
if not asp.main then
|
||||
asp.main = {
|
||||
free = true,
|
||||
}
|
||||
elseif type(asp.main) ~= "table" then
|
||||
asp.main = {
|
||||
free = asp.main~=0,
|
||||
speed = asp.main,
|
||||
}
|
||||
end
|
||||
if not asp.dst then
|
||||
asp.dst = {
|
||||
free = true,
|
||||
}
|
||||
end
|
||||
if not asp.shunt then
|
||||
asp.shunt = {
|
||||
free = false,
|
||||
proceed_as_main = false,
|
||||
}
|
||||
elseif type(asp.shunt) ~= "table" then
|
||||
asp.shunt = {
|
||||
free = asp.shunt,
|
||||
proceed_as_main = asp.proceed_as_main,
|
||||
}
|
||||
end
|
||||
if not asp.info then
|
||||
asp.info = {}
|
||||
end
|
||||
@ -458,8 +432,10 @@ function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_
|
||||
local form = "size[7,5]label[0.5,0.5;Select Signal Aspect:]"
|
||||
form = form.."label[0.5,1;"..purpose.."]"
|
||||
|
||||
|
||||
--TODO
|
||||
form = form.."label[0.5,1.5;== Main Signal ==]"
|
||||
if suppasp.main.free == nil then
|
||||
if suppasp.main == 0 then
|
||||
local st = 2
|
||||
if isasp and not isasp.main.free then st=1 end
|
||||
form = form.."dropdown[0.5,2;2;main_free;danger,free;"..st.."]"
|
||||
|
@ -95,24 +95,47 @@ Cancels the route that is set from the signal at pos. Has the same effect as cli
|
||||
|
||||
get_aspect(pos)
|
||||
Returns the signal aspect of the signal at pos. A signal aspect has the following format:
|
||||
aspect = {
|
||||
main = { -- the next track section in line. Shows blocked for shunt routes
|
||||
free = <boolean>,
|
||||
speed = <int km/h>,
|
||||
},
|
||||
shunt = { -- whether a "shunting allowed" aspect should be shown
|
||||
free = <boolean>,
|
||||
}
|
||||
dst = { -- the aspect of the next main signal on (at end of) route
|
||||
free = <boolean>,
|
||||
speed = <int km/h>,
|
||||
}
|
||||
asp = {
|
||||
main = <int speed>,
|
||||
-- Main signal aspect, tells state and permitted speed of next section
|
||||
-- 0 = section is blocked
|
||||
-- >0 = section is free, speed limit is this value
|
||||
-- -1 = section is free, maximum speed permitted
|
||||
-- false = Signal doesn't provide main signal information, retain current speed limit.
|
||||
shunt = <boolean>,
|
||||
-- Whether train may proceed as shunt move, on sight
|
||||
-- main aspect takes precedence over this
|
||||
-- When main==0, train switches to shunt move and is restricted to speed 8
|
||||
proceed_as_main = <boolean>,
|
||||
-- If an approaching train is a shunt move and 'shunt' is false,
|
||||
-- the train may proceed as a train move under the "main" aspect
|
||||
-- if the main aspect permits it (i.e. main!=0)
|
||||
-- If this is not set, shunt moves are NOT allowed to switch to
|
||||
-- a train move, and must stop even if "main" would permit passing.
|
||||
-- This is intended to be used for "Halt for shunt moves" signs.
|
||||
|
||||
dst = <int speed>,
|
||||
-- Distant signal aspect, tells state and permitted speed of the section after next section
|
||||
-- The character of these information is purely informational
|
||||
-- At this time, this field is not actively used
|
||||
-- 0 = section is blocked
|
||||
-- >0 = section is free, speed limit is this value
|
||||
-- -1 = section is free, maximum speed permitted
|
||||
-- false = Signal doesn't provide distant signal information.
|
||||
|
||||
info = {
|
||||
call_on = <boolean>, -- Call-on route, expect train in track ahead
|
||||
dead_end = <boolean>, -- Route ends on a dead end (e.g. bumper)
|
||||
-- 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 August 2018, only the aspect.main.free field is ever used by the interlocking system.
|
||||
As of January 2020, the 'dst', 'call_on' and 'dead_end' fields are not used.
|
||||
|
||||
# Lines
|
||||
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
local setaspectf = function(rot)
|
||||
return function(pos, node, asp)
|
||||
if not asp.main.free then
|
||||
if asp.shunt.free then
|
||||
if asp.main == 0 then
|
||||
if asp.shunt then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_shunt_"..rot, param2 = node.param2})
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_danger_"..rot, param2 = node.param2})
|
||||
end
|
||||
else
|
||||
if asp.dst.free and asp.main.speed == -1 then
|
||||
if asp.dst != 0 and asp.main == -1 then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_free_"..rot, param2 = node.param2})
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:hs_slow_"..rot, param2 = node.param2})
|
||||
@ -22,19 +22,12 @@ local setaspectf = function(rot)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local suppasp = {
|
||||
main = {
|
||||
free = nil,
|
||||
speed = {6, -1},
|
||||
},
|
||||
dst = {
|
||||
free = nil,
|
||||
speed = nil,
|
||||
},
|
||||
shunt = {
|
||||
free = nil,
|
||||
main = {0, 6, -1},
|
||||
dst = {0, false},
|
||||
shunt = nil,
|
||||
proceed_as_main = true,
|
||||
},
|
||||
info = {
|
||||
call_on = false,
|
||||
dead_end = false,
|
||||
@ -45,7 +38,7 @@ local suppasp = {
|
||||
--Rangiersignal
|
||||
local setaspectf_ra = function(rot)
|
||||
return function(pos, node, asp)
|
||||
if asp.shunt.free then
|
||||
if asp.shunt then
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:ra_shuntd_"..rot, param2 = node.param2})
|
||||
else
|
||||
advtrains.ndb.swap_node(pos, {name="advtrains_signals_ks:ra_danger_"..rot, param2 = node.param2})
|
||||
@ -58,17 +51,11 @@ local setaspectf_ra = function(rot)
|
||||
end
|
||||
|
||||
local suppasp_ra = {
|
||||
main = {
|
||||
free = true,
|
||||
},
|
||||
dst = {
|
||||
free = nil,
|
||||
speed = nil,
|
||||
},
|
||||
shunt = {
|
||||
free = nil,
|
||||
main = { false },
|
||||
dst = { false },
|
||||
shunt = nil,
|
||||
proceed_as_main = false,
|
||||
},
|
||||
|
||||
info = {
|
||||
call_on = false,
|
||||
dead_end = false,
|
||||
@ -90,9 +77,9 @@ for _, rtab in ipairs({
|
||||
local rot = rtab.rot
|
||||
for typ, prts in pairs({
|
||||
danger = {asp = advtrains.interlocking.DANGER, n = "slow", ici=true},
|
||||
slow = {asp = { main = { free = true, speed = 6 }, shunt = {proceed_as_main = true}} , n = "free"},
|
||||
free = {asp = { main = { free = true, speed = -1 }, shunt = {proceed_as_main = true}} , n = "shunt"},
|
||||
shunt = {asp = { main = {free = false}, shunt = {free = true} } , n = "danger"},
|
||||
slow = {asp = { main = 6, proceed_as_main = true} , n = "free"},
|
||||
free = {asp = { main = -1, proceed_as_main = true} , n = "shunt"},
|
||||
shunt = {asp = { main = 0, shunt = true} , n = "danger"},
|
||||
}) do
|
||||
minetest.register_node("advtrains_signals_ks:hs_"..typ.."_"..rot, {
|
||||
description = "Ks Main Signal",
|
||||
@ -136,8 +123,8 @@ for _, rtab in ipairs({
|
||||
|
||||
--Rangiersignale:
|
||||
for typ, prts in pairs({
|
||||
danger = {asp = { main = {free = true}, shunt = {free = false} }, n = "shuntd", ici=true},
|
||||
shuntd = {asp = { main = {free = true}, shunt = {free = true} } , n = "danger"},
|
||||
danger = {asp = { main = false, shunt = false }, n = "shuntd", ici=true},
|
||||
shuntd = {asp = { main = false, shunt = true } , n = "danger"},
|
||||
}) do
|
||||
minetest.register_node("advtrains_signals_ks:ra_"..typ.."_"..rot, {
|
||||
description = "Ks Shunting Signal",
|
||||
@ -181,13 +168,13 @@ for _, rtab in ipairs({
|
||||
--Schilder:
|
||||
for typ, prts in pairs({
|
||||
-- Speed restrictions:
|
||||
["8"] = {asp = { main = {free = true, speed = 8}, shunt = {free = true} }, n = "12", ici=true},
|
||||
["12"] = {asp = { main = {free = true, speed = 12}, shunt = {free = true} }, n = "16"},
|
||||
["16"] = {asp = { main = {free = true, speed = 16}, shunt = {free = true} }, n = "e"},
|
||||
["8"] = {asp = { main = 8, shunt = true }, n = "12", ici=true},
|
||||
["12"] = {asp = { main = 12, shunt = true }, n = "16"},
|
||||
["16"] = {asp = { main = 16, shunt = true }, n = "e"},
|
||||
-- Speed restriction lifted
|
||||
["e"] = {asp = { main = {free = true, speed = -1}, shunt = {free = true} }, n = "hfs"},
|
||||
["e"] = {asp = { main = -1, shunt = true }, n = "hfs"},
|
||||
-- Halt for shunt moves:
|
||||
["hfs"] = {asp = { main = {free = true}, shunt = {free = false} }, n = "8"},
|
||||
["hfs"] = {asp = { main = false, shunt = false }, n = "8"},
|
||||
}) do
|
||||
minetest.register_node("advtrains_signals_ks:sign_"..typ.."_"..rot, {
|
||||
description = "Signal Sign",
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- Ks Signals for advtrains
|
||||
-- will implement the advtrains signal API (which does not exist yet)
|
||||
-- will implement the advtrains signal API
|
||||
|
||||
local function place_degrotate(pos, placer, itemstack, pointed_thing)
|
||||
local yaw = placer:get_look_horizontal()
|
||||
|
Loading…
x
Reference in New Issue
Block a user