koishi-plugin-tmp-bot 1.18.7 → 1.19.0
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/api/evmOpenApi.d.ts +6 -0
- package/lib/api/evmOpenApi.js +22 -0
- package/lib/command/tmpBind.js +3 -2
- package/lib/command/tmpFootprint.d.ts +3 -0
- package/lib/command/tmpFootprint.js +66 -0
- package/lib/command/tmpPosition.d.ts +1 -1
- package/lib/command/tmpQuery/tmpQueryImg.d.ts +1 -1
- package/lib/index.js +2 -0
- package/lib/resource/footprint.html +240 -0
- package/lib/resource/package/ets-map.js +63 -0
- package/lib/util/constant.d.ts +7 -0
- package/lib/util/constant.js +14 -1
- package/package.json +1 -1
- package/readme.md +13 -12
package/lib/api/evmOpenApi.d.ts
CHANGED
|
@@ -31,3 +31,9 @@ export function dlcList(http: any, type: any): Promise<{
|
|
|
31
31
|
export function mileageRankingList(http: any, rankingType: any, tmpId: any): Promise<{
|
|
32
32
|
error: boolean;
|
|
33
33
|
}>;
|
|
34
|
+
/**
|
|
35
|
+
* 查询玩家历史数据
|
|
36
|
+
*/
|
|
37
|
+
export function mapPlayerHistory(http: any, tmpId: any, serverId: any, startTime: any, endTime: any): Promise<{
|
|
38
|
+
error: boolean;
|
|
39
|
+
}>;
|
package/lib/api/evmOpenApi.js
CHANGED
|
@@ -110,5 +110,27 @@ module.exports = {
|
|
|
110
110
|
data.data = result.data;
|
|
111
111
|
}
|
|
112
112
|
return data;
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* 查询玩家历史数据
|
|
116
|
+
*/
|
|
117
|
+
async mapPlayerHistory(http, tmpId, serverId, startTime, endTime) {
|
|
118
|
+
let result = null;
|
|
119
|
+
try {
|
|
120
|
+
result = await http.get(`${BASE_API}/map/playerHistory?tmpId=${tmpId}&serverId=${serverId}&startTime=${startTime}&endTime=${endTime}`);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return {
|
|
124
|
+
error: true
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// 拼接返回数据
|
|
128
|
+
let data = {
|
|
129
|
+
error: result.code !== 200
|
|
130
|
+
};
|
|
131
|
+
if (!data.error) {
|
|
132
|
+
data.data = result.data;
|
|
133
|
+
}
|
|
134
|
+
return data;
|
|
113
135
|
}
|
|
114
136
|
};
|
package/lib/command/tmpBind.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const guildBind = require('../database/guildBind');
|
|
2
2
|
const truckersMpApi = require("../api/truckersMpApi");
|
|
3
|
+
const evmOpenApi = require('../api/evmOpenApi');
|
|
3
4
|
/**
|
|
4
5
|
* 绑定 TMP ID
|
|
5
6
|
*/
|
|
@@ -8,11 +9,11 @@ module.exports = async (ctx, cfg, session, tmpId) => {
|
|
|
8
9
|
return `请输入正确的玩家编号`;
|
|
9
10
|
}
|
|
10
11
|
// 查询玩家信息
|
|
11
|
-
let playerInfo = await
|
|
12
|
+
let playerInfo = await evmOpenApi.playerInfo(ctx.http, tmpId);
|
|
12
13
|
if (playerInfo.error) {
|
|
13
14
|
return '绑定失败 (查询玩家信息失败)';
|
|
14
15
|
}
|
|
15
16
|
// 更新数据库
|
|
16
|
-
guildBind.saveOrUpdate(ctx.database, session.platform, session.userId, tmpId);
|
|
17
|
+
guildBind.saveOrUpdate(ctx.database, session.platform, session.userId, playerInfo.data.tmpId);
|
|
17
18
|
return `绑定成功 ( ${playerInfo.data.name} )`;
|
|
18
19
|
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const { segment } = require('koishi');
|
|
2
|
+
const { resolve } = require('path');
|
|
3
|
+
const common = require('../util/common');
|
|
4
|
+
const { ServerAliasToId, PromodsIds } = require('../util/constant');
|
|
5
|
+
const evmOpenApi = require('../api/evmOpenApi');
|
|
6
|
+
const guildBind = require('../database/guildBind');
|
|
7
|
+
module.exports = async (ctx, session, serverName) => {
|
|
8
|
+
if (!ctx.puppeteer) {
|
|
9
|
+
return '未启用 puppeteer 服务';
|
|
10
|
+
}
|
|
11
|
+
// 转换服务器别名到ID
|
|
12
|
+
let serverId = ServerAliasToId[serverName];
|
|
13
|
+
if (!serverId) {
|
|
14
|
+
return '请输入正确的服务器名称 (s1, s2, p, a)';
|
|
15
|
+
}
|
|
16
|
+
// 尝试从数据库查询绑定信息
|
|
17
|
+
let guildBindData = await guildBind.get(ctx.database, session.platform, session.userId);
|
|
18
|
+
if (!guildBindData) {
|
|
19
|
+
return `请输入正确的玩家编号`;
|
|
20
|
+
}
|
|
21
|
+
let tmpId = guildBindData.tmp_id;
|
|
22
|
+
// 查询玩家信息
|
|
23
|
+
let playerInfo = await evmOpenApi.playerInfo(ctx.http, tmpId);
|
|
24
|
+
if (playerInfo.error && playerInfo.code === 10001) {
|
|
25
|
+
return '玩家不存在';
|
|
26
|
+
}
|
|
27
|
+
else if (playerInfo.error) {
|
|
28
|
+
return '查询玩家信息失败,请重试';
|
|
29
|
+
}
|
|
30
|
+
// 查询当日历史位置数据
|
|
31
|
+
let mapPlayerHistory = await evmOpenApi.mapPlayerHistory(ctx.http, tmpId, serverId, '2026-01-22 00:00:00', '2026-01-22 23:00:00');
|
|
32
|
+
if (mapPlayerHistory.data.length === 0) {
|
|
33
|
+
return `当日暂无数据`;
|
|
34
|
+
}
|
|
35
|
+
// 拼接数据
|
|
36
|
+
let data = {
|
|
37
|
+
mapType: PromodsIds.indexOf(serverId) !== -1 ? 'promods' : 'ets',
|
|
38
|
+
name: playerInfo.data.name,
|
|
39
|
+
smallAvatarUrl: playerInfo.data.smallAvatarUrl,
|
|
40
|
+
todayMileage: playerInfo.data.todayMileage,
|
|
41
|
+
points: mapPlayerHistory.data
|
|
42
|
+
};
|
|
43
|
+
console.info(data.mapType);
|
|
44
|
+
let page;
|
|
45
|
+
try {
|
|
46
|
+
page = await ctx.puppeteer.page();
|
|
47
|
+
await page.setViewport({ width: 1000, height: 1000 });
|
|
48
|
+
await page.goto(`file:///${resolve(__dirname, '../resource/footprint.html')}`);
|
|
49
|
+
await page.evaluate(`init(${JSON.stringify(data)})`);
|
|
50
|
+
await common.sleep(100);
|
|
51
|
+
await page.waitForNetworkIdle();
|
|
52
|
+
const element = await page.$("#container");
|
|
53
|
+
return (segment.image(await element.screenshot({
|
|
54
|
+
encoding: "binary"
|
|
55
|
+
}), "image/jpg"));
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
return '渲染异常,请重试';
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
if (page) {
|
|
62
|
+
await page.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return `OK: ` + playerInfo.data.name;
|
|
66
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare function _exports(ctx: any, cfg: any, session: any, tmpId: any): Promise<segment | "请输入正确的玩家编号" | "渲染异常,请重试" | "
|
|
1
|
+
declare function _exports(ctx: any, cfg: any, session: any, tmpId: any): Promise<segment | "请输入正确的玩家编号" | "渲染异常,请重试" | "未启用 puppeteer 服务" | "查询玩家信息失败,请重试" | "玩家离线">;
|
|
2
2
|
export = _exports;
|
|
3
3
|
import { segment } from "@koishijs/core";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare function _exports(ctx: any, cfg: any, session: any, tmpId: any): Promise<segment | "请输入正确的玩家编号" | "渲染异常,请重试" | "
|
|
1
|
+
declare function _exports(ctx: any, cfg: any, session: any, tmpId: any): Promise<segment | "请输入正确的玩家编号" | "渲染异常,请重试" | "未启用 puppeteer 服务" | "玩家不存在" | "查询玩家信息失败,请重试">;
|
|
2
2
|
export = _exports;
|
|
3
3
|
import { segment } from "@koishijs/core";
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const tmpPosition = require('./command/tmpPosition');
|
|
|
13
13
|
const tmpVersion = require('./command/tmpVersion');
|
|
14
14
|
const tmpDlcMap = require('./command/tmpDlcMap');
|
|
15
15
|
const tmpMileageRanking = require('./command/tmpMileageRanking');
|
|
16
|
+
const tmpFootprint = require('./command/tmpFootprint');
|
|
16
17
|
exports.name = 'tmp-bot';
|
|
17
18
|
exports.inject = {
|
|
18
19
|
required: ['database'],
|
|
@@ -50,4 +51,5 @@ function apply(ctx, cfg) {
|
|
|
50
51
|
ctx.command('tmpdlcmap').action(async ({ session }) => await tmpDlcMap(ctx, session));
|
|
51
52
|
ctx.command('tmpmileageranking').action(async ({ session }) => await tmpMileageRanking(ctx, session, MileageRankingType.total));
|
|
52
53
|
ctx.command('tmptodaymileageranking').action(async ({ session }) => await tmpMileageRanking(ctx, session, MileageRankingType.today));
|
|
54
|
+
ctx.command('tmpfootprint').action(async ({ session }, serverName) => await tmpFootprint(ctx, session, serverName));
|
|
53
55
|
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>玩家足迹展示</title>
|
|
6
|
+
<link href="./package/leaflet/leaflet.min.css" rel="stylesheet">
|
|
7
|
+
<script src="./package/leaflet/leaflet.min.js"></script>
|
|
8
|
+
<style>
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'segui-emj';
|
|
11
|
+
src: url('./package/SEGUIEMJ.TTF');
|
|
12
|
+
font-weight: normal;
|
|
13
|
+
font-style: normal;
|
|
14
|
+
}
|
|
15
|
+
body, html {
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
font-family: 'segui-emj', "微软雅黑", serif;
|
|
19
|
+
}
|
|
20
|
+
#container {
|
|
21
|
+
width: 800px;
|
|
22
|
+
height: 600px;
|
|
23
|
+
background: #1a1a1a;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
position: relative;
|
|
26
|
+
}
|
|
27
|
+
.status-bar {
|
|
28
|
+
position: absolute;
|
|
29
|
+
bottom: 0;
|
|
30
|
+
left: 0;
|
|
31
|
+
right: 0;
|
|
32
|
+
height: 32px;
|
|
33
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
34
|
+
backdrop-filter: blur(10px);
|
|
35
|
+
-webkit-backdrop-filter: blur(10px);
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
padding: 0 12px;
|
|
39
|
+
box-shadow: 0 -2px 10px rgba(0, 0, 0, .5);
|
|
40
|
+
z-index: 1001;
|
|
41
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
42
|
+
font-size: 13px;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
}
|
|
45
|
+
.status-bar .avatar {
|
|
46
|
+
width: 20px;
|
|
47
|
+
height: 20px;
|
|
48
|
+
border-radius: 4px;
|
|
49
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
50
|
+
margin-right: 8px;
|
|
51
|
+
}
|
|
52
|
+
.status-bar .info {
|
|
53
|
+
flex: 1;
|
|
54
|
+
display: flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
}
|
|
57
|
+
.status-bar .info .name {
|
|
58
|
+
color: #b0c7ff;
|
|
59
|
+
font-weight: 600;
|
|
60
|
+
}
|
|
61
|
+
.status-bar .stats {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
color: #aaaaaa;
|
|
65
|
+
}
|
|
66
|
+
.status-bar .stats .label {
|
|
67
|
+
margin-right: 6px;
|
|
68
|
+
}
|
|
69
|
+
.status-bar .stats .value {
|
|
70
|
+
font-weight: bold;
|
|
71
|
+
color: #54d354;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#map-box {
|
|
75
|
+
width: 100%;
|
|
76
|
+
height: 100%;
|
|
77
|
+
}
|
|
78
|
+
#map {
|
|
79
|
+
width: 100%;
|
|
80
|
+
height: 100%;
|
|
81
|
+
background-color: rgba(0, 0, 0, 0.25);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.marker-label {
|
|
85
|
+
background: rgba(0, 0, 0, 0.6);
|
|
86
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
87
|
+
border-radius: 4px;
|
|
88
|
+
color: #fff;
|
|
89
|
+
padding: 2px 6px;
|
|
90
|
+
font-size: 12px;
|
|
91
|
+
white-space: nowrap;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body>
|
|
96
|
+
<div id="container">
|
|
97
|
+
<div id="map-box">
|
|
98
|
+
<div id="map"></div>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="status-bar">
|
|
101
|
+
<img class="avatar" id="avatar" src="https://static.truckersmp.com/avatarsN/small/defaultavatar.png" alt="avatar"/>
|
|
102
|
+
<div class="info">
|
|
103
|
+
<div class="name" id="username">测试玩家</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="stats" id="stats-box">
|
|
106
|
+
<span class="label">今日里程</span>
|
|
107
|
+
<span class="value" id="distance">0.0 km</span>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<script src="./package/ets-map.js"></script>
|
|
113
|
+
<script>
|
|
114
|
+
function calculateDistance(p1, p2) {
|
|
115
|
+
return Math.sqrt(Math.pow(p1.axisX - p2.axisX, 2) + Math.pow(p1.axisY - p2.axisY, 2));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function parseTime(timeStr) {
|
|
119
|
+
return new Date(timeStr.replace(/-/g, '/')).getTime();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function init(data) {
|
|
123
|
+
if (!data) return;
|
|
124
|
+
|
|
125
|
+
document.getElementById('username').innerText = (data.name || 'Unknown') + ' 的今日行驶足迹';
|
|
126
|
+
if (data.smallAvatarUrl) {
|
|
127
|
+
document.getElementById('avatar').src = data.smallAvatarUrl;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const points = data.points || [];
|
|
131
|
+
// 使用传入的今日里程数据(米转千米)
|
|
132
|
+
const mileage = data.todayMileage || 0;
|
|
133
|
+
const km = (mileage / 1000).toFixed(1);
|
|
134
|
+
document.getElementById('distance').innerText = `${km} km`;
|
|
135
|
+
|
|
136
|
+
if (points.length === 0) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const lines = [];
|
|
141
|
+
let currentLine = [];
|
|
142
|
+
|
|
143
|
+
if (points.length > 0) {
|
|
144
|
+
let first = points[0];
|
|
145
|
+
currentLine.push({ x: first.axisX, y: first.axisY });
|
|
146
|
+
|
|
147
|
+
for (let i = 1; i < points.length; i++) {
|
|
148
|
+
const prev = points[i - 1];
|
|
149
|
+
const curr = points[i];
|
|
150
|
+
|
|
151
|
+
const dist = calculateDistance(prev, curr);
|
|
152
|
+
const isDistJump = dist > 2632; // > 50km
|
|
153
|
+
|
|
154
|
+
let timeDiff = 0;
|
|
155
|
+
try {
|
|
156
|
+
timeDiff = (parseTime(curr.updateTime) - parseTime(prev.updateTime)) / 1000;
|
|
157
|
+
} catch (e) { }
|
|
158
|
+
|
|
159
|
+
const isTimeJump = timeDiff > 60;
|
|
160
|
+
const isServerJump = prev.serverId !== curr.serverId;
|
|
161
|
+
|
|
162
|
+
if (isDistJump || isTimeJump || isServerJump) {
|
|
163
|
+
if (currentLine.length > 0) lines.push(currentLine);
|
|
164
|
+
currentLine = [];
|
|
165
|
+
}
|
|
166
|
+
currentLine.push({ x: curr.axisX, y: curr.axisY });
|
|
167
|
+
}
|
|
168
|
+
if (currentLine.length > 0) lines.push(currentLine);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
render(lines, data.mapType);
|
|
172
|
+
}
|
|
173
|
+
function render(lines, mapType) {
|
|
174
|
+
const config = mapConfig[mapType];
|
|
175
|
+
|
|
176
|
+
// 边界
|
|
177
|
+
let bounds = L.latLngBounds(
|
|
178
|
+
map.unproject([0, config.bounds.y], config.maxZoom),
|
|
179
|
+
map.unproject([config.bounds.x, 0], config.maxZoom)
|
|
180
|
+
);
|
|
181
|
+
map.setMaxBounds(bounds);
|
|
182
|
+
|
|
183
|
+
// 瓦片
|
|
184
|
+
L.tileLayer(config.tileUrl, {
|
|
185
|
+
minZoom: 0,
|
|
186
|
+
maxZoom: 8,
|
|
187
|
+
minNativeZoom: 2,
|
|
188
|
+
maxNativeZoom: 8,
|
|
189
|
+
tileSize: 512,
|
|
190
|
+
bounds: bounds,
|
|
191
|
+
reuseTiles: true
|
|
192
|
+
}).addTo(map);
|
|
193
|
+
|
|
194
|
+
let allLatlngs = [];
|
|
195
|
+
|
|
196
|
+
lines.forEach(points => {
|
|
197
|
+
if (!points || points.length === 0) return;
|
|
198
|
+
|
|
199
|
+
let latlngs = [];
|
|
200
|
+
points.forEach(xy => {
|
|
201
|
+
let unprojected = map.unproject(config.calculateMapCoordinate(xy.x, xy.y), 8);
|
|
202
|
+
latlngs.push([unprojected.lat, unprojected.lng]);
|
|
203
|
+
allLatlngs.push([unprojected.lat, unprojected.lng]);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// 轨迹线
|
|
207
|
+
L.polyline(latlngs, {
|
|
208
|
+
color: '#3498db',
|
|
209
|
+
weight: 4,
|
|
210
|
+
opacity: 0.8,
|
|
211
|
+
lineJoin: 'round'
|
|
212
|
+
}).addTo(map);
|
|
213
|
+
|
|
214
|
+
// 起点
|
|
215
|
+
L.circleMarker(latlngs[0], {
|
|
216
|
+
radius: 4,
|
|
217
|
+
fillColor: '#2ecc71',
|
|
218
|
+
color: '#fff',
|
|
219
|
+
weight: 2,
|
|
220
|
+
fillOpacity: 1
|
|
221
|
+
}).addTo(map);
|
|
222
|
+
|
|
223
|
+
// 终点
|
|
224
|
+
L.circleMarker(latlngs[latlngs.length - 1], {
|
|
225
|
+
radius: 4,
|
|
226
|
+
fillColor: '#e74c3c',
|
|
227
|
+
color: '#fff',
|
|
228
|
+
weight: 2,
|
|
229
|
+
fillOpacity: 1
|
|
230
|
+
}).addTo(map);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// 自动适应
|
|
234
|
+
if (allLatlngs.length > 0) {
|
|
235
|
+
map.fitBounds(L.latLngBounds(allLatlngs), { padding: [50, 50] });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
</script>
|
|
239
|
+
</body>
|
|
240
|
+
</html>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
let mapConfig = {
|
|
2
|
+
ets: {
|
|
3
|
+
tileUrl: 'https://ets-map.oss-cn-beijing.aliyuncs.com/ets2/05102019/{z}/{x}/{y}.png',
|
|
4
|
+
multipliers: {
|
|
5
|
+
x: 70272,
|
|
6
|
+
y: 76157
|
|
7
|
+
},
|
|
8
|
+
breakpoints: {
|
|
9
|
+
uk: {
|
|
10
|
+
x: -31056.8,
|
|
11
|
+
y: -5832.867
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
bounds: {
|
|
15
|
+
y: 131072,
|
|
16
|
+
x: 131072
|
|
17
|
+
},
|
|
18
|
+
maxZoom: 8,
|
|
19
|
+
minZoom: 2,
|
|
20
|
+
// 游戏地转地图坐标
|
|
21
|
+
calculateMapCoordinate (x, y) {
|
|
22
|
+
return [
|
|
23
|
+
x / 1.609055 + mapConfig.ets.multipliers.x,
|
|
24
|
+
y / 1.609055 + mapConfig.ets.multipliers.y
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
promods: {
|
|
29
|
+
tileUrl: 'https://ets-map.oss-cn-beijing.aliyuncs.com/promods/05102019/{z}/{x}/{y}.png',
|
|
30
|
+
multipliers: {
|
|
31
|
+
x: 51953,
|
|
32
|
+
y: 76024
|
|
33
|
+
},
|
|
34
|
+
breakpoints: {
|
|
35
|
+
uk: {
|
|
36
|
+
x: -31056.8,
|
|
37
|
+
y: -5832.867
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
bounds: {
|
|
41
|
+
y: 131072,
|
|
42
|
+
x: 131072
|
|
43
|
+
},
|
|
44
|
+
maxZoom: 8,
|
|
45
|
+
minZoom: 2,
|
|
46
|
+
// 游戏地转地图坐标
|
|
47
|
+
calculateMapCoordinate (x, y) {
|
|
48
|
+
return [
|
|
49
|
+
x / 2.598541 + mapConfig.promods.multipliers.x,
|
|
50
|
+
y / 2.598541 + mapConfig.promods.multipliers.y
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 定义地图
|
|
57
|
+
let map = L.map('map', {
|
|
58
|
+
attributionControl: false,
|
|
59
|
+
crs: L.CRS.Simple,
|
|
60
|
+
zoomControl: false,
|
|
61
|
+
zoomSnap: 0.2,
|
|
62
|
+
zoomDelta: 0.2
|
|
63
|
+
});
|
package/lib/util/constant.d.ts
CHANGED
package/lib/util/constant.js
CHANGED
|
@@ -12,5 +12,18 @@ module.exports = {
|
|
|
12
12
|
MileageRankingType: {
|
|
13
13
|
total: 1,
|
|
14
14
|
today: 2
|
|
15
|
-
}
|
|
15
|
+
},
|
|
16
|
+
/**
|
|
17
|
+
* 服务器别名映射ID
|
|
18
|
+
*/
|
|
19
|
+
ServerAliasToId: {
|
|
20
|
+
's1': 2,
|
|
21
|
+
's2': 41,
|
|
22
|
+
'p': 50,
|
|
23
|
+
'a': 7
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* P服务器ID集合
|
|
27
|
+
*/
|
|
28
|
+
PromodsIds: [50, 51]
|
|
16
29
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-tmp-bot",
|
|
3
3
|
"description": "欧洲卡车模拟2 TMP查询插件,不会部署的可以直接使用此机器人->QQ:3523283907",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.19.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"homepage": "https://github.com/79887143/koishi-plugin-tmp-bot",
|
package/readme.md
CHANGED
|
@@ -5,18 +5,19 @@
|
|
|
5
5
|
欧洲卡车模拟2 TMP查询机器人
|
|
6
6
|
|
|
7
7
|
### 指令说明
|
|
8
|
-
| 指令名称 | 指令介绍
|
|
9
|
-
|
|
10
|
-
| tmpbind | 绑定 TMPID,绑定后使用其他指令时可省略输入
|
|
11
|
-
| tmpquery | 查询TMP玩家信息
|
|
12
|
-
| tmpposition | 查询玩家位置信息
|
|
13
|
-
| tmptraffic | 查询服务器热门地点路况信息,仅支持使用服务器简称查询,具体支持查询的服务器和服务器简称信息如下</br>Simulation 1 (简称: s1)</br>Simulation 2 (简称: s2)</br>ProMods (简称: p)</br>Arcade (简称: a)
|
|
14
|
-
| tmpserverats | 查询美卡服务器信息列表
|
|
15
|
-
| tmpserverets | 查询欧卡服务器信息列表
|
|
16
|
-
| tmpversion | 查询版本信息
|
|
17
|
-
| tmpdlcmap | 地图DLC列表
|
|
18
|
-
| tmpmileageranking | 总里程排行榜,数据从 2025年8月23日20:00 开始统计,绑定ID后可查看自己的排名
|
|
19
|
-
| tmptodaymileageranking | 今日里程排行榜,每日0点重置数据,绑定ID后可查看自己的排名
|
|
8
|
+
| 指令名称 | 指令介绍 | 使用示例 |
|
|
9
|
+
|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|
|
|
10
|
+
| tmpbind | 绑定 TMPID,绑定后使用其他指令时可省略输入 | tmpbind 123 |
|
|
11
|
+
| tmpquery | 查询TMP玩家信息 | tmpquery 123 |
|
|
12
|
+
| tmpposition | 查询玩家位置信息 | tmpposition 123 |
|
|
13
|
+
| tmptraffic | 查询服务器热门地点路况信息,仅支持使用服务器简称查询,具体支持查询的服务器和服务器简称信息如下</br>Simulation 1 (简称: s1)</br>Simulation 2 (简称: s2)</br>ProMods (简称: p)</br>Arcade (简称: a) | tmptraffic s1 |
|
|
14
|
+
| tmpserverats | 查询美卡服务器信息列表 | tmpserverats |
|
|
15
|
+
| tmpserverets | 查询欧卡服务器信息列表 | tmpserverets |
|
|
16
|
+
| tmpversion | 查询版本信息 | tmpversion |
|
|
17
|
+
| tmpdlcmap | 地图DLC列表 | tmpdlcmap |
|
|
18
|
+
| tmpmileageranking | 总里程排行榜,数据从 2025年8月23日20:00 开始统计,绑定ID后可查看自己的排名 | tmpmileageranking |
|
|
19
|
+
| tmptodaymileageranking | 今日里程排行榜,每日0点重置数据,绑定ID后可查看自己的排名 | tmptodaymileageranking |
|
|
20
|
+
| tmpfootprint | 今日足迹,仅支持使用服务器简称查询,具体支持查询的服务器和服务器简称信息如下</br>Simulation 1 (简称: s1)</br>Simulation 2 (简称: s2)</br>ProMods (简称: p)</br>Arcade (简称: a) | tmpfootprint s1 |
|
|
20
21
|
|
|
21
22
|
### TMP数据接口文档
|
|
22
23
|
https://apifox.com/apidoc/shared/38508a88-5ff4-4b29-b724-41f9d3d3336a
|