koishi-plugin-ets2-tools-tmp 3.1.1 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/command/tmpFootprint.js +1 -1
- package/lib/command/tmpQuery/tmpQueryImg.js +1 -0
- package/lib/index.js +1 -1
- package/lib/resource/dlc.html +150 -42
- package/lib/resource/mileage-leaderboard.html +448 -247
- package/lib/resource/query.html +20 -7
- package/lib/resource/server-list.html +264 -112
- package/lib/resource/traffic.html +246 -116
- package/package.json +1 -1
|
@@ -8,135 +8,265 @@
|
|
|
8
8
|
<script src="./package/leaflet/heatmap.min.js"></script>
|
|
9
9
|
<script src="./package/leaflet/leaflet-heatmap.js"></script>
|
|
10
10
|
<style>
|
|
11
|
-
body, html {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
* {
|
|
16
|
-
font-family: "微软雅黑", serif;
|
|
17
|
-
}
|
|
11
|
+
body, html { margin: 0; padding: 0; }
|
|
12
|
+
* { font-family: "微软雅黑", serif; }
|
|
13
|
+
|
|
18
14
|
#container {
|
|
19
15
|
width: 1000px;
|
|
20
16
|
position: relative;
|
|
21
17
|
}
|
|
18
|
+
|
|
22
19
|
.map {
|
|
23
20
|
width: 100%;
|
|
24
21
|
height: 900px;
|
|
25
|
-
background-color: #
|
|
22
|
+
background-color: #1a1a2e;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Map overlay frame - cyber corners */
|
|
26
|
+
.map-frame {
|
|
27
|
+
position: absolute;
|
|
28
|
+
inset: 0;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
z-index: 999;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.corner {
|
|
34
|
+
position: absolute;
|
|
35
|
+
width: 24px;
|
|
36
|
+
height: 24px;
|
|
37
|
+
border-color: rgba(0, 200, 255, 0.4);
|
|
38
|
+
border-style: solid;
|
|
26
39
|
}
|
|
40
|
+
|
|
41
|
+
.corner.tl { top: 0; left: 0; border-width: 2px 0 0 2px; }
|
|
42
|
+
.corner.tr { top: 0; right: 0; border-width: 2px 2px 0 0; }
|
|
43
|
+
.corner.bl { bottom: 0; left: 0; border-width: 0 0 2px 2px; }
|
|
44
|
+
.corner.br { bottom: 0; right: 0; border-width: 0 2px 2px 0; }
|
|
45
|
+
|
|
46
|
+
/* Map title overlay */
|
|
47
|
+
.map-title {
|
|
48
|
+
position: absolute;
|
|
49
|
+
top: 12px;
|
|
50
|
+
left: 16px;
|
|
51
|
+
z-index: 1000;
|
|
52
|
+
pointer-events: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.map-title-icon {
|
|
56
|
+
font-size: 16px;
|
|
57
|
+
filter: drop-shadow(0 0 6px rgba(0, 200, 255, 0.5));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.map-title-text {
|
|
61
|
+
font-size: 12px;
|
|
62
|
+
font-weight: 800;
|
|
63
|
+
color: rgba(0, 200, 255, 0.6);
|
|
64
|
+
letter-spacing: 2px;
|
|
65
|
+
text-transform: uppercase;
|
|
66
|
+
margin-top: 2px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Player count badge */
|
|
70
|
+
.player-badge {
|
|
71
|
+
position: absolute;
|
|
72
|
+
top: 12px;
|
|
73
|
+
right: 16px;
|
|
74
|
+
z-index: 1000;
|
|
75
|
+
pointer-events: none;
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 6px;
|
|
79
|
+
padding: 4px 10px;
|
|
80
|
+
background: rgba(0, 0, 0, 0.6);
|
|
81
|
+
border: 1px solid rgba(0, 200, 255, 0.2);
|
|
82
|
+
border-radius: 6px;
|
|
83
|
+
backdrop-filter: blur(8px);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.player-badge-dot {
|
|
87
|
+
width: 6px;
|
|
88
|
+
height: 6px;
|
|
89
|
+
border-radius: 50%;
|
|
90
|
+
background: #00ff88;
|
|
91
|
+
box-shadow: 0 0 4px rgba(0, 255, 136, 0.6);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.player-badge-text {
|
|
95
|
+
font-size: 11px;
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
color: #00c8ff;
|
|
98
|
+
text-shadow: 0 0 4px rgba(0, 200, 255, 0.3);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ===== TRAFFIC BOX ===== */
|
|
27
102
|
.traffic-box {
|
|
28
|
-
//position: absolute;
|
|
29
|
-
//bottom: 0;
|
|
30
|
-
//left: 0;
|
|
31
|
-
//z-index: 9999999;
|
|
32
103
|
width: 100%;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
padding: 12px 16px;
|
|
104
|
+
background: linear-gradient(180deg, #0d0d1a 0%, #0a0a14 100%);
|
|
105
|
+
padding: 0;
|
|
36
106
|
box-sizing: border-box;
|
|
37
|
-
overflow
|
|
107
|
+
overflow: hidden;
|
|
108
|
+
position: relative;
|
|
38
109
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
110
|
+
|
|
111
|
+
.traffic-header {
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: 8px;
|
|
115
|
+
padding: 10px 16px 6px;
|
|
116
|
+
border-bottom: 1px solid rgba(0, 200, 255, 0.08);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.traffic-header-icon {
|
|
44
120
|
font-size: 14px;
|
|
45
|
-
|
|
121
|
+
filter: drop-shadow(0 0 4px rgba(0, 200, 255, 0.4));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.traffic-header-text {
|
|
125
|
+
font-size: 11px;
|
|
126
|
+
font-weight: 800;
|
|
127
|
+
color: #556;
|
|
128
|
+
letter-spacing: 1.5px;
|
|
129
|
+
text-transform: uppercase;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.traffic-grid {
|
|
133
|
+
display: grid;
|
|
134
|
+
grid-template-columns: repeat(3, 1fr);
|
|
135
|
+
gap: 0;
|
|
136
|
+
padding: 0 12px 10px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.traffic-item {
|
|
140
|
+
color: #c0c8d0;
|
|
141
|
+
padding: 8px 10px;
|
|
142
|
+
border-right: 1px solid rgba(0, 200, 255, 0.06);
|
|
143
|
+
border-bottom: 1px solid rgba(0, 200, 255, 0.04);
|
|
144
|
+
font-size: 12px;
|
|
46
145
|
box-sizing: border-box;
|
|
47
|
-
padding: 0 10px;
|
|
48
146
|
display: flex;
|
|
49
147
|
flex-direction: row;
|
|
50
148
|
align-items: center;
|
|
51
|
-
|
|
149
|
+
gap: 6px;
|
|
52
150
|
}
|
|
53
|
-
|
|
54
|
-
|
|
151
|
+
|
|
152
|
+
.traffic-item:nth-child(3n) {
|
|
153
|
+
border-right: none;
|
|
55
154
|
}
|
|
56
|
-
|
|
57
|
-
|
|
155
|
+
|
|
156
|
+
.traffic-item:nth-last-child(-n+3) {
|
|
157
|
+
border-bottom: none;
|
|
58
158
|
}
|
|
159
|
+
|
|
59
160
|
.traffic-item .region-info {
|
|
60
|
-
|
|
61
|
-
width:
|
|
161
|
+
flex: 1;
|
|
162
|
+
min-width: 0;
|
|
62
163
|
white-space: nowrap;
|
|
63
164
|
overflow: hidden;
|
|
64
165
|
text-overflow: ellipsis;
|
|
65
166
|
}
|
|
167
|
+
|
|
168
|
+
.traffic-item .region-info strong {
|
|
169
|
+
color: #d0e0ff;
|
|
170
|
+
font-weight: 700;
|
|
171
|
+
}
|
|
172
|
+
|
|
66
173
|
.traffic-item .player-count {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
174
|
+
font-size: 12px;
|
|
175
|
+
font-weight: 800;
|
|
176
|
+
color: #00c8ff;
|
|
177
|
+
text-shadow: 0 0 4px rgba(0, 200, 255, 0.2);
|
|
178
|
+
flex-shrink: 0;
|
|
70
179
|
}
|
|
180
|
+
|
|
71
181
|
.traffic-item .traffic-status {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
182
|
+
font-size: 10px;
|
|
183
|
+
font-weight: 700;
|
|
184
|
+
padding: 1px 6px;
|
|
185
|
+
border-radius: 4px;
|
|
186
|
+
flex-shrink: 0;
|
|
187
|
+
text-transform: uppercase;
|
|
188
|
+
letter-spacing: 0.5px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.status-fluid {
|
|
192
|
+
color: #00d26a;
|
|
193
|
+
background: rgba(0, 210, 106, 0.1);
|
|
194
|
+
border: 1px solid rgba(0, 210, 106, 0.2);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.status-moderate {
|
|
198
|
+
color: #ff6723;
|
|
199
|
+
background: rgba(255, 103, 35, 0.1);
|
|
200
|
+
border: 1px solid rgba(255, 103, 35, 0.2);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.status-congested {
|
|
204
|
+
color: #f8312f;
|
|
205
|
+
background: rgba(248, 49, 47, 0.1);
|
|
206
|
+
border: 1px solid rgba(248, 49, 47, 0.2);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.status-heavy {
|
|
210
|
+
color: #8d67c5;
|
|
211
|
+
background: rgba(141, 103, 197, 0.1);
|
|
212
|
+
border: 1px solid rgba(141, 103, 197, 0.2);
|
|
75
213
|
}
|
|
76
214
|
</style>
|
|
77
215
|
</head>
|
|
78
216
|
<body>
|
|
79
217
|
<div id="container">
|
|
80
218
|
<div id="map" class="map"></div>
|
|
81
|
-
|
|
219
|
+
|
|
220
|
+
<div class="map-frame">
|
|
221
|
+
<div class="corner tl"></div>
|
|
222
|
+
<div class="corner tr"></div>
|
|
223
|
+
<div class="corner bl"></div>
|
|
224
|
+
<div class="corner br"></div>
|
|
225
|
+
</div>
|
|
226
|
+
|
|
227
|
+
<div class="map-title">
|
|
228
|
+
<div class="map-title-icon">🗺️</div>
|
|
229
|
+
<div class="map-title-text">LIVE HEATMAP</div>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<div class="player-badge">
|
|
233
|
+
<div class="player-badge-dot"></div>
|
|
234
|
+
<div class="player-badge-text" id="player-count">0 在线</div>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div class="traffic-box">
|
|
238
|
+
<div class="traffic-header">
|
|
239
|
+
<span class="traffic-header-icon">📊</span>
|
|
240
|
+
<span class="traffic-header-text">热门区域路况</span>
|
|
241
|
+
</div>
|
|
242
|
+
<div class="traffic-grid" id="traffic-grid"></div>
|
|
243
|
+
</div>
|
|
82
244
|
</div>
|
|
245
|
+
|
|
83
246
|
<script>
|
|
84
247
|
let mapConfig = {
|
|
85
248
|
ets: {
|
|
86
249
|
tileUrl: 'https://ets-map.oss-cn-beijing.aliyuncs.com/ets2/05102019/{z}/{x}/{y}.png',
|
|
87
|
-
multipliers: {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
x: -31056.8,
|
|
94
|
-
y: -5832.867
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
bounds: {
|
|
98
|
-
y: 131072,
|
|
99
|
-
x: 131072
|
|
100
|
-
},
|
|
101
|
-
maxZoom: 8,
|
|
102
|
-
minZoom: 2,
|
|
103
|
-
// 游戏地转地图坐标
|
|
104
|
-
calculateMapCoordinate (x, y) {
|
|
105
|
-
return [
|
|
106
|
-
x / 1.609055 + mapConfig.ets.multipliers.x,
|
|
107
|
-
y / 1.609055 + mapConfig.ets.multipliers.y
|
|
108
|
-
];
|
|
250
|
+
multipliers: { x: 70272, y: 76157 },
|
|
251
|
+
breakpoints: { uk: { x: -31056.8, y: -5832.867 } },
|
|
252
|
+
bounds: { y: 131072, x: 131072 },
|
|
253
|
+
maxZoom: 8, minZoom: 2,
|
|
254
|
+
calculateMapCoordinate(x, y) {
|
|
255
|
+
return [x / 1.609055 + mapConfig.ets.multipliers.x, y / 1.609055 + mapConfig.ets.multipliers.y];
|
|
109
256
|
}
|
|
110
257
|
},
|
|
111
258
|
promods: {
|
|
112
|
-
tileUrl: 'https://
|
|
113
|
-
multipliers: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
x: -31056.8,
|
|
120
|
-
y: -5832.867
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
bounds: {
|
|
124
|
-
y: 131072,
|
|
125
|
-
x: 131072
|
|
126
|
-
},
|
|
127
|
-
maxZoom: 8,
|
|
128
|
-
minZoom: 2,
|
|
129
|
-
// 游戏地转地图坐标
|
|
130
|
-
calculateMapCoordinate (x, y) {
|
|
131
|
-
return [
|
|
132
|
-
x / 2.598541 + mapConfig.promods.multipliers.x,
|
|
133
|
-
y / 2.598541 + mapConfig.promods.multipliers.y
|
|
134
|
-
]
|
|
259
|
+
tileUrl: 'https://ets6-map.oss-cn-beijing.aliyuncs.com/promods/05102019/{z}/{x}/{y}.png',
|
|
260
|
+
multipliers: { x: 51953, y: 76024 },
|
|
261
|
+
breakpoints: { uk: { x: -31056.8, y: -5832.867 } },
|
|
262
|
+
bounds: { y: 131072, x: 131072 },
|
|
263
|
+
maxZoom: 8, minZoom: 2,
|
|
264
|
+
calculateMapCoordinate(x, y) {
|
|
265
|
+
return [x / 2.598541 + mapConfig.promods.multipliers.x, y / 2.598541 + mapConfig.promods.multipliers.y];
|
|
135
266
|
}
|
|
136
267
|
}
|
|
137
|
-
}
|
|
268
|
+
};
|
|
138
269
|
|
|
139
|
-
// 定义地图
|
|
140
270
|
let map = L.map('map', {
|
|
141
271
|
attributionControl: false,
|
|
142
272
|
crs: L.CRS.Simple,
|
|
@@ -144,62 +274,62 @@
|
|
|
144
274
|
zoomSnap: 0.1
|
|
145
275
|
});
|
|
146
276
|
|
|
277
|
+
const statusClassMap = {
|
|
278
|
+
'畅通': 'status-fluid',
|
|
279
|
+
'正常': 'status-moderate',
|
|
280
|
+
'缓慢': 'status-congested',
|
|
281
|
+
'拥堵': 'status-heavy'
|
|
282
|
+
};
|
|
283
|
+
|
|
147
284
|
function setData(data) {
|
|
148
|
-
// 边界
|
|
149
285
|
let bounds = L.latLngBounds(
|
|
150
286
|
map.unproject([0, mapConfig[data.mapType].bounds.y], mapConfig[data.mapType].maxZoom),
|
|
151
287
|
map.unproject([mapConfig[data.mapType].bounds.x, 0], mapConfig[data.mapType].maxZoom)
|
|
152
288
|
);
|
|
153
289
|
|
|
154
|
-
// 瓦片地图
|
|
155
290
|
L.tileLayer(mapConfig[data.mapType].tileUrl, {
|
|
156
|
-
minZoom: 0,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
maxNativeZoom: 8,
|
|
160
|
-
tileSize: 512,
|
|
161
|
-
bounds: bounds,
|
|
162
|
-
reuseTiles: true
|
|
291
|
+
minZoom: 0, maxZoom: 8,
|
|
292
|
+
minNativeZoom: 1, maxNativeZoom: 8,
|
|
293
|
+
tileSize: 512, bounds: bounds, reuseTiles: true
|
|
163
294
|
}).addTo(map);
|
|
164
|
-
map.setMaxBounds(
|
|
165
|
-
new L.LatLngBounds(
|
|
166
|
-
map.unproject([0, mapConfig[data.mapType].bounds.y], mapConfig[data.mapType].maxZoom),
|
|
167
|
-
map.unproject([mapConfig[data.mapType].bounds.x, 0], mapConfig[data.mapType].maxZoom)
|
|
168
|
-
)
|
|
169
|
-
);
|
|
170
295
|
|
|
171
|
-
|
|
172
|
-
|
|
296
|
+
map.setMaxBounds(new L.LatLngBounds(
|
|
297
|
+
map.unproject([0, mapConfig[data.mapType].bounds.y], mapConfig[data.mapType].maxZoom),
|
|
298
|
+
map.unproject([mapConfig[data.mapType].bounds.x, 0], mapConfig[data.mapType].maxZoom)
|
|
299
|
+
));
|
|
300
|
+
|
|
301
|
+
map.fitBounds(bounds);
|
|
173
302
|
|
|
174
|
-
//
|
|
303
|
+
// Heatmap
|
|
175
304
|
let heatmapLayer = new HeatmapOverlay({
|
|
176
305
|
radius: 3,
|
|
177
306
|
maxOpacity: 0.8,
|
|
178
307
|
scaleRadius: true,
|
|
179
308
|
useLocalExtrema: true,
|
|
180
|
-
latField: "lat",
|
|
181
|
-
lngField: "lng",
|
|
182
|
-
valueField: "count"
|
|
309
|
+
latField: "lat", lngField: "lng", valueField: "count"
|
|
183
310
|
});
|
|
184
311
|
map.addLayer(heatmapLayer);
|
|
185
|
-
|
|
312
|
+
|
|
313
|
+
let heatmapData = [];
|
|
186
314
|
for (const arrayElement of data.playerCoordinateList) {
|
|
187
315
|
let unprojected = map.unproject(mapConfig[data.mapType].calculateMapCoordinate(arrayElement[0], arrayElement[1]), 8);
|
|
188
316
|
heatmapData.push({ lat: unprojected.lat, lng: unprojected.lng, count: 1 });
|
|
189
317
|
}
|
|
190
|
-
heatmapLayer.setData({
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
})
|
|
318
|
+
heatmapLayer.setData({ min: 1, max: 5000, data: heatmapData });
|
|
319
|
+
|
|
320
|
+
// Player count badge
|
|
321
|
+
document.getElementById('player-count').textContent = data.playerCoordinateList.length.toLocaleString() + ' 在线';
|
|
195
322
|
|
|
196
|
-
//
|
|
323
|
+
// Traffic grid
|
|
324
|
+
const grid = document.getElementById('traffic-grid');
|
|
197
325
|
for (const traffic of data.trafficList) {
|
|
198
|
-
|
|
326
|
+
const cls = statusClassMap[traffic.severity.text] || '';
|
|
327
|
+
grid.insertAdjacentHTML('beforeend', `
|
|
199
328
|
<div class="traffic-item">
|
|
200
|
-
<span class="region-info"><strong>${traffic.country}</strong> ${traffic.province}</span
|
|
201
|
-
|
|
202
|
-
|
|
329
|
+
<span class="region-info"><strong>${traffic.country}</strong> ${traffic.province}</span>
|
|
330
|
+
<span class="player-count">${traffic.playerCount}</span>
|
|
331
|
+
<span class="traffic-status ${cls}">${traffic.severity.text}</span>
|
|
332
|
+
</div>`);
|
|
203
333
|
}
|
|
204
334
|
}
|
|
205
335
|
</script>
|