Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f7fbca3e5e | |||
| 9695eaa28a | |||
| 0d7546a510 | |||
| 9dc8136240 | |||
| a02a83f8bd | |||
| 9b18f55d29 | |||
| a3434e7ae9 | |||
| 64b15028e4 | |||
| d8e466fdaa | |||
| 43bbe8f2ae |
@@ -1,3 +1,15 @@
|
|||||||
|
|
||||||
|
# 5.6.2
|
||||||
|
- Changes from 5.6.0
|
||||||
|
- Bugfixes
|
||||||
|
- Fix incorrect forward datasources getter in facade
|
||||||
|
- Fix include `access=private` non-car roads in the car profile
|
||||||
|
|
||||||
|
# 5.6.1
|
||||||
|
- Changes from 5.6.0
|
||||||
|
- Bugfixes
|
||||||
|
- Fix #3754 restricted access roads not penalized if restriction begins non at an intersection
|
||||||
|
|
||||||
# 5.6.0
|
# 5.6.0
|
||||||
- Changes from 5.5
|
- Changes from 5.5
|
||||||
- Bugfixes
|
- Bugfixes
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ Feature: Car - Restricted access
|
|||||||
| motorway | yes | permissive | | private | x | | implied oneway |
|
| motorway | yes | permissive | | private | x | | implied oneway |
|
||||||
| trunk | agricultural | designated | permissive | no | | | |
|
| trunk | agricultural | designated | permissive | no | | | |
|
||||||
| pedestrian | | | | | | | |
|
| pedestrian | | | | | | | |
|
||||||
| pedestrian | | | | destination | x | x | |
|
| pedestrian | | | | destination | | | temporary disabled #3773 |
|
||||||
|
|
||||||
Scenario: Car - Ignore access tags for other modes
|
Scenario: Car - Ignore access tags for other modes
|
||||||
Then routability should be
|
Then routability should be
|
||||||
@@ -202,8 +202,9 @@ Feature: Car - Restricted access
|
|||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate |
|
| highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate |
|
||||||
| primary | designated | designated | | | x | x | 18 | 18 |
|
| primary | designated | designated | | | x | x | 18 | 18 |
|
||||||
| primary | | designated | | | x | x | 18 | 18 |
|
# This test is flaky because non-deterministic turn generation sometimes emits a NoTurn here that is marked as restricted. #3769
|
||||||
| primary | designated | | | | x | x | 18 | 18 |
|
#| primary | | designated | | | x | x | 18 | 18 |
|
||||||
|
#| primary | designated | | | | x | x | 18 | 18 |
|
||||||
| primary | designated\|designated | designated\|designated | | | x | x | 18 | 18 |
|
| primary | designated\|designated | designated\|designated | | | x | x | 18 | 18 |
|
||||||
| primary | designated\|no | designated\|no | | | x | x | 18 | 18 |
|
| primary | designated\|no | designated\|no | | | x | x | 18 | 18 |
|
||||||
| primary | yes\|no | yes\|no | | | x | x | 18 | 18 |
|
| primary | yes\|no | yes\|no | | | x | x | 18 | 18 |
|
||||||
@@ -261,9 +262,11 @@ Feature: Car - Restricted access
|
|||||||
|
|
||||||
Scenario: Car - a way with a list of tags
|
Scenario: Car - a way with a list of tags
|
||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | motor_vehicle | motor_vehicle:forward | motor_vehicle:backward | forw | backw |
|
| highway | motor_vehicle | motor_vehicle:forward | motor_vehicle:backward | forw | backw | # |
|
||||||
| footway | | | destination | | x |
|
| primary | | no | destination | | x | |
|
||||||
| track | destination;agricultural | destination | | x | x |
|
| primary | destination;agricultural | destination | | x | x | |
|
||||||
|
| footway | | | destination | | | temporary #3373 |
|
||||||
|
| track | destination;agricultural | destination | | | x | temporary #3373 |
|
||||||
|
|
||||||
Scenario: Car - Don't route over steps even if marked as accessible
|
Scenario: Car - Don't route over steps even if marked as accessible
|
||||||
Then routability should be
|
Then routability should be
|
||||||
@@ -279,3 +282,24 @@ Feature: Car - Restricted access
|
|||||||
| steps | permissive | |
|
| steps | permissive | |
|
||||||
| footway | permissive | x |
|
| footway | permissive | x |
|
||||||
| garbagetag | permissive | x |
|
| garbagetag | permissive | x |
|
||||||
|
|
||||||
|
Scenario: Car - Access private blacklist
|
||||||
|
Then routability should be
|
||||||
|
| highway | access | bothw |
|
||||||
|
| footway | yes | x |
|
||||||
|
| pedestrian | private | |
|
||||||
|
| footway | private | |
|
||||||
|
| service | private | |
|
||||||
|
| cycleway | private | |
|
||||||
|
| track | private | |
|
||||||
|
|
||||||
|
Scenario: Car - Access blacklist
|
||||||
|
Then routability should be
|
||||||
|
| highway | access | bothw |
|
||||||
|
| primary | | x |
|
||||||
|
| primary | customer | |
|
||||||
|
| primary | emergency | |
|
||||||
|
| primary | forestry | |
|
||||||
|
| primary | agricultural | |
|
||||||
|
| primary | psv | |
|
||||||
|
| primary | no | |
|
||||||
|
|||||||
@@ -81,3 +81,53 @@ Feature: Car - Destination only, no passing through
|
|||||||
| e | a | de,cd,bc,ab,ab |
|
| e | a | de,cd,bc,ab,ab |
|
||||||
| b | d | bc,cd,cd |
|
| b | d | bc,cd,cd |
|
||||||
| d | b | cd,bc,bc |
|
| d | b | cd,bc,bc |
|
||||||
|
|
||||||
|
Scenario: Car - Routing around a way that becomes destination only
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
b
|
||||||
|
\
|
||||||
|
|
|
||||||
|
e++d++++++c--i
|
||||||
|
| \
|
||||||
|
\ h--a
|
||||||
|
\ |
|
||||||
|
\___________g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | access | oneway |
|
||||||
|
| ah | | no |
|
||||||
|
| ihg | | no |
|
||||||
|
| eg | | no |
|
||||||
|
| icde | | no |
|
||||||
|
| cde | destination | no |
|
||||||
|
| eb | | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | # |
|
||||||
|
| i | b | ihg,eg,eb,eb | # goes around access=destination, though restricted way starts at two node intersection |
|
||||||
|
| b | d | eb,cde,cde | # ends in restricted way correctly |
|
||||||
|
| b | i | eb,eg,ihg,ihg | # goes around restricted way correctly |
|
||||||
|
|
||||||
|
Scenario: Car - Routing around a way that becomes destination only
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---c---b
|
||||||
|
+ \
|
||||||
|
+ |
|
||||||
|
d |
|
||||||
|
\___e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | access | oneway |
|
||||||
|
| acbe | | no |
|
||||||
|
| cd | destination | no |
|
||||||
|
| de | | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| e | a | acbe,acbe |
|
||||||
|
| d | a | de,acbe,acbe |
|
||||||
|
| c | d | cd,cd |
|
||||||
|
|||||||
@@ -28,13 +28,14 @@ module.exports = function () {
|
|||||||
directions.filter(d => headers.has(d + '_rate')).forEach((direction) => {
|
directions.filter(d => headers.has(d + '_rate')).forEach((direction) => {
|
||||||
var rate = direction + '_rate';
|
var rate = direction + '_rate';
|
||||||
var want = row[rate];
|
var want = row[rate];
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case '' === want:
|
case '' === want:
|
||||||
outputRow[rate] = result[direction].status ?
|
outputRow[rate] = result[direction].status ?
|
||||||
result[direction].status.toString() : '';
|
result[direction].status.toString() : '';
|
||||||
break;
|
break;
|
||||||
case /^\d+$/.test(want):
|
case /^\d+$/.test(want):
|
||||||
if (result[direction].rate && !isNaN(result[direction].rate)) {
|
if (result[direction].rate !== undefined && !isNaN(result[direction].rate)) {
|
||||||
outputRow[rate] = result[direction].rate.toString();
|
outputRow[rate] = result[direction].rate.toString();
|
||||||
} else {
|
} else {
|
||||||
outputRow[rate] = '';
|
outputRow[rate] = '';
|
||||||
|
|||||||
@@ -36,15 +36,18 @@ Feature: Traffic - speeds
|
|||||||
1,4,27
|
1,4,27
|
||||||
4,1,27
|
4,1,27
|
||||||
"""
|
"""
|
||||||
And I route I should get
|
And the query options
|
||||||
| from | to | route | speed | weights |
|
| annotations | datasources |
|
||||||
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
|
|
||||||
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 |
|
When I route I should get
|
||||||
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
| from | to | route | speed | weights | a:datasources |
|
||||||
| a | d | ad,ad | 27 km/h | 1275.7,0 |
|
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0:0 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 |
|
||||||
| g | b | fb,fb | 36 km/h | 164.7,0 |
|
| b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
|
||||||
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 |
|
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1:0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
||||||
|
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
|
||||||
|
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | 1:0:0 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file weights, ETA based on file durations
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
@@ -58,15 +61,18 @@ Feature: Traffic - speeds
|
|||||||
1,4,27,1275.7
|
1,4,27,1275.7
|
||||||
4,1,27,1275.7
|
4,1,27,1275.7
|
||||||
"""
|
"""
|
||||||
And I route I should get
|
And the query options
|
||||||
| from | to | route | speed | weights |
|
| annotations | datasources |
|
||||||
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
|
|
||||||
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 |
|
When I route I should get
|
||||||
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
| from | to | route | speed | weights | a:datasources |
|
||||||
| a | d | ad,ad | 27 km/h | 1275.7,0 |
|
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0:0 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 |
|
||||||
| g | b | ab,ab | 1 km/h | 10010.4,0 |
|
| b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
|
||||||
| a | g | ab,ab | 1 km/h | 10010.3,0 |
|
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1:0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
||||||
|
| g | b | ab,ab | 1 km/h | 10010.4,0 | 1:0 |
|
||||||
|
| a | g | ab,ab | 1 km/h | 10010.3,0 | 1 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file weights, ETA based on file durations
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
@@ -87,16 +93,19 @@ Feature: Traffic - speeds
|
|||||||
1,4,1,34445.12
|
1,4,1,34445.12
|
||||||
4,1,1,34445.3
|
4,1,1,34445.3
|
||||||
"""
|
"""
|
||||||
And I route I should get
|
And the query options
|
||||||
| from | to | route | speed | weights |
|
| annotations | datasources |
|
||||||
| a | b | ab,ab | 1 km/h | 20020.789,0 |
|
|
||||||
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 |
|
When I route I should get
|
||||||
| b | c | bc,bc | 27 km/h | 741.568,0 |
|
| from | to | route | speed | weights | a:datasources |
|
||||||
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 |
|
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.805,0 |
|
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
|
||||||
| g | b | ab,ab | 1 km/h | 10010.392,0 |
|
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
|
||||||
| a | g | ab,ab | 1 km/h | 10010.397,0 |
|
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
|
||||||
| g | a | ab,ab | 1 km/h | 10010.064,0 |
|
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
|
||||||
|
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
|
||||||
|
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
|
||||||
|
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Speeds that isolate a single node (a)
|
Scenario: Speeds that isolate a single node (a)
|
||||||
@@ -113,15 +122,18 @@ Feature: Traffic - speeds
|
|||||||
1,4,0
|
1,4,0
|
||||||
4,1,0
|
4,1,0
|
||||||
"""
|
"""
|
||||||
And I route I should get
|
And the query options
|
||||||
| from | to | route | speed | weights |
|
| annotations | true |
|
||||||
| a | b | fb,fb | 36 km/h | 329.4,0 |
|
|
||||||
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 |
|
When I route I should get
|
||||||
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
| from | to | route | speed | weights | a:datasources |
|
||||||
| a | d | fb,df,df | 36 km/h | 140,487.5,0 |
|
| a | b | fb,fb | 36 km/h | 329.4,0 | 0 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | 0:1:0 |
|
||||||
| g | b | fb,fb | 36 km/h | 164.7,0 |
|
| b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
|
||||||
| a | g | fb,fb | 36 km/h | 164.7,0 |
|
| a | d | fb,df,df | 36 km/h | 140,487.5,0 | 0:0:0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
||||||
|
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
|
||||||
|
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Verify that negative values cause an error, they're not valid at all
|
Scenario: Verify that negative values cause an error, they're not valid at all
|
||||||
|
|||||||
@@ -865,7 +865,6 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result_datasources.resize(end - begin);
|
|
||||||
std::copy(m_datasource_list.begin() + begin,
|
std::copy(m_datasource_list.begin() + begin,
|
||||||
m_datasource_list.begin() + end,
|
m_datasource_list.begin() + end,
|
||||||
std::back_inserter(result_datasources));
|
std::back_inserter(result_datasources));
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ local profile = {
|
|||||||
|
|
||||||
restricted_access_tag_list = Set { },
|
restricted_access_tag_list = Set { },
|
||||||
|
|
||||||
|
restricted_highway_whitelist = Set { },
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
access_tags_hierarchy = Sequence {
|
||||||
'bicycle',
|
'bicycle',
|
||||||
'vehicle',
|
'vehicle',
|
||||||
|
|||||||
+22
-3
@@ -74,7 +74,11 @@ local profile = {
|
|||||||
'agricultural',
|
'agricultural',
|
||||||
'forestry',
|
'forestry',
|
||||||
'emergency',
|
'emergency',
|
||||||
'psv'
|
'psv',
|
||||||
|
'customer',
|
||||||
|
'private',
|
||||||
|
'delivery',
|
||||||
|
'destination'
|
||||||
},
|
},
|
||||||
|
|
||||||
restricted_access_tag_list = Set {
|
restricted_access_tag_list = Set {
|
||||||
@@ -137,6 +141,21 @@ local profile = {
|
|||||||
["drive-thru"] = 0.5
|
["drive-thru"] = 0.5
|
||||||
},
|
},
|
||||||
|
|
||||||
|
restricted_highway_whitelist = Set {
|
||||||
|
'motorway',
|
||||||
|
'motorway_link',
|
||||||
|
'trunk',
|
||||||
|
'trunk_link',
|
||||||
|
'primary',
|
||||||
|
'primary_link',
|
||||||
|
'secondary',
|
||||||
|
'secondary_link',
|
||||||
|
'tertiary',
|
||||||
|
'tertiary_link',
|
||||||
|
'residential',
|
||||||
|
'living_street',
|
||||||
|
},
|
||||||
|
|
||||||
route_speeds = {
|
route_speeds = {
|
||||||
ferry = 5,
|
ferry = 5,
|
||||||
shuttle_train = 10
|
shuttle_train = 10
|
||||||
@@ -259,7 +278,7 @@ function node_function (node, result)
|
|||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
if profile.access_tag_blacklist[access] then
|
if profile.access_tag_blacklist[access] and not profile.restricted_access_tag_list[access] then
|
||||||
result.barrier = true
|
result.barrier = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -392,11 +411,11 @@ function turn_function (turn)
|
|||||||
else
|
else
|
||||||
turn.weight = turn.duration
|
turn.weight = turn.duration
|
||||||
end
|
end
|
||||||
|
end
|
||||||
if properties.weight_name == 'routability' then
|
if properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + profile.restricted_penalty
|
turn.weight = turn.weight + profile.restricted_penalty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ local profile = {
|
|||||||
|
|
||||||
restricted_access_tag_list = Set { },
|
restricted_access_tag_list = Set { },
|
||||||
|
|
||||||
|
restricted_highway_whitelist = Set { },
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
access_tags_hierarchy = Sequence {
|
||||||
'foot',
|
'foot',
|
||||||
'access'
|
'access'
|
||||||
|
|||||||
+15
-12
@@ -212,18 +212,8 @@ function Handlers.handle_access(way,result,data,profile)
|
|||||||
data.forward_access, data.backward_access =
|
data.forward_access, data.backward_access =
|
||||||
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
|
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
|
||||||
|
|
||||||
if profile.access_tag_blacklist[data.forward_access] then
|
-- only allow a subset of roads that are marked as restricted
|
||||||
result.forward_mode = mode.inaccessible
|
if profile.restricted_highway_whitelist[data.highway] then
|
||||||
end
|
|
||||||
|
|
||||||
if profile.access_tag_blacklist[data.backward_access] then
|
|
||||||
result.backward_mode = mode.inaccessible
|
|
||||||
end
|
|
||||||
|
|
||||||
if result.forward_mode == mode.inaccessible and result.backward_mode == mode.inaccessible then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if profile.restricted_access_tag_list[data.forward_access] then
|
if profile.restricted_access_tag_list[data.forward_access] then
|
||||||
result.forward_restricted = true
|
result.forward_restricted = true
|
||||||
end
|
end
|
||||||
@@ -231,6 +221,19 @@ function Handlers.handle_access(way,result,data,profile)
|
|||||||
if profile.restricted_access_tag_list[data.backward_access] then
|
if profile.restricted_access_tag_list[data.backward_access] then
|
||||||
result.backward_restricted = true
|
result.backward_restricted = true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if profile.access_tag_blacklist[data.forward_access] and not result.forward_restricted then
|
||||||
|
result.forward_mode = mode.inaccessible
|
||||||
|
end
|
||||||
|
|
||||||
|
if profile.access_tag_blacklist[data.backward_access] and not result.backward_restricted then
|
||||||
|
result.backward_mode = mode.inaccessible
|
||||||
|
end
|
||||||
|
|
||||||
|
if result.forward_mode == mode.inaccessible and result.backward_mode == mode.inaccessible then
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle speed (excluding maxspeed)
|
-- handle speed (excluding maxspeed)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(test_tile)
|
|||||||
const auto rc = osrm.Tile(params, result);
|
const auto rc = osrm.Tile(params, result);
|
||||||
BOOST_CHECK(rc == Status::Ok);
|
BOOST_CHECK(rc == Status::Ok);
|
||||||
|
|
||||||
BOOST_CHECK(result.size() > 115000);
|
BOOST_CHECK(result.size() > 114000);
|
||||||
|
|
||||||
protozero::pbf_reader tile_message(result);
|
protozero::pbf_reader tile_message(result);
|
||||||
tile_message.next();
|
tile_message.next();
|
||||||
|
|||||||
Reference in New Issue
Block a user