kotori-plugin-minecraft 1.0.0 → 1.0.2
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/index.d.ts +1 -1
- package/lib/index.js +144 -113
- package/lib/utils/bedrock.d.ts +1 -0
- package/lib/utils/bedrock.js +121 -0
- package/lib/utils/java.d.ts +1 -0
- package/lib/utils/java.js +126 -0
- package/locales/en_US.json +13 -0
- package/locales/ja_JP.json +13 -0
- package/locales/zh_TW.json +13 -0
- package/package.json +3 -6
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,121 +1,152 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @Package kotori-plugin-minecraft
|
|
4
|
+
* @Version 1.0.2
|
|
5
|
+
* @Author Hotaru <me@hotaru.icu>
|
|
6
|
+
* @Copyright 2024 Hotaru. All rights reserved.
|
|
7
|
+
* @License GPL-3.0
|
|
8
|
+
* @Link https://github.com/kotorijs/kotori
|
|
9
|
+
* @Date 2024/8/8 20:54:12
|
|
10
|
+
*/
|
|
11
|
+
|
|
1
12
|
"use strict";
|
|
2
|
-
Object.defineProperty
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
icon: kotori_bot_1.Tsu.Unknown()
|
|
24
|
-
})
|
|
25
|
-
])
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
15
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
16
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
|
+
};
|
|
21
|
+
var __copyProps = (to, from, except, desc) => {
|
|
22
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
23
|
+
for (let key of __getOwnPropNames(from))
|
|
24
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
25
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
26
|
+
}
|
|
27
|
+
return to;
|
|
28
|
+
};
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var src_exports = {};
|
|
31
|
+
__export(src_exports, {
|
|
32
|
+
lang: () => lang,
|
|
33
|
+
main: () => main
|
|
26
34
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
kotori_bot_1.Tsu.Null().optional(),
|
|
51
|
-
kotori_bot_1.Tsu.Object({
|
|
52
|
-
skin: kotori_bot_1.Tsu.String(),
|
|
53
|
-
cape: kotori_bot_1.Tsu.String().optional(),
|
|
54
|
-
avatar: kotori_bot_1.Tsu.String()
|
|
55
|
-
})
|
|
56
|
-
])
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
var import_kotori_bot = require("kotori-bot");
|
|
37
|
+
const lang = [__dirname, "../locales"];
|
|
38
|
+
const motdSchema = import_kotori_bot.Tsu.Object({
|
|
39
|
+
data: import_kotori_bot.Tsu.Union(
|
|
40
|
+
import_kotori_bot.Tsu.Object({
|
|
41
|
+
status: import_kotori_bot.Tsu.Literal("offline")
|
|
42
|
+
}),
|
|
43
|
+
import_kotori_bot.Tsu.Object({
|
|
44
|
+
status: import_kotori_bot.Tsu.Literal("online"),
|
|
45
|
+
ip: import_kotori_bot.Tsu.String(),
|
|
46
|
+
real: import_kotori_bot.Tsu.String(),
|
|
47
|
+
location: import_kotori_bot.Tsu.String(),
|
|
48
|
+
port: import_kotori_bot.Tsu.String(),
|
|
49
|
+
motd: import_kotori_bot.Tsu.String(),
|
|
50
|
+
version: import_kotori_bot.Tsu.String(),
|
|
51
|
+
agreement: import_kotori_bot.Tsu.Number(),
|
|
52
|
+
online: import_kotori_bot.Tsu.Number(),
|
|
53
|
+
max: import_kotori_bot.Tsu.Number(),
|
|
54
|
+
ping: import_kotori_bot.Tsu.Number(),
|
|
55
|
+
icon: import_kotori_bot.Tsu.Unknown()
|
|
56
|
+
})
|
|
57
|
+
)
|
|
57
58
|
});
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const motdbeSchema = import_kotori_bot.Tsu.Object({
|
|
60
|
+
data: import_kotori_bot.Tsu.Union(
|
|
61
|
+
import_kotori_bot.Tsu.Object({
|
|
62
|
+
status: import_kotori_bot.Tsu.Literal("offline")
|
|
62
63
|
}),
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
import_kotori_bot.Tsu.Object({
|
|
65
|
+
status: import_kotori_bot.Tsu.Literal("online"),
|
|
66
|
+
ip: import_kotori_bot.Tsu.String(),
|
|
67
|
+
real: import_kotori_bot.Tsu.String(),
|
|
68
|
+
location: import_kotori_bot.Tsu.String(),
|
|
69
|
+
port: import_kotori_bot.Tsu.Number(),
|
|
70
|
+
motd: import_kotori_bot.Tsu.String(),
|
|
71
|
+
version: import_kotori_bot.Tsu.String(),
|
|
72
|
+
agreement: import_kotori_bot.Tsu.Number(),
|
|
73
|
+
online: import_kotori_bot.Tsu.Number(),
|
|
74
|
+
max: import_kotori_bot.Tsu.Number(),
|
|
75
|
+
delay: import_kotori_bot.Tsu.Number(),
|
|
76
|
+
gamemode: import_kotori_bot.Tsu.String()
|
|
77
|
+
})
|
|
78
|
+
)
|
|
67
79
|
});
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (res.data.status !== 'online')
|
|
76
|
-
return ['minecraft.msg.motd.fail', [data.args[0], data.args[1]]];
|
|
77
|
-
const { ip, port, location, motd, agreement, version, online, max, ping } = res.data;
|
|
78
|
-
const icon = typeof res.data.icon === 'string' ? session.el.image(`base64://${res.data.icon.substring(22)}`) : '';
|
|
79
|
-
return ['minecraft.msg.motd', [ip, port, location, motd, agreement, version, online, max, ping, icon]];
|
|
80
|
-
});
|
|
81
|
-
ctx.command('motdbe <ip> [port:number=19132] - minecraft.descr.motdbe').action(async (data) => {
|
|
82
|
-
const res = motdbeSchema.parse(await ctx.http.get('https://api.hotaru.icu/api/motdpe', { ip: data.args[0], port: data.args[1] }));
|
|
83
|
-
if (res.data.status !== 'online')
|
|
84
|
-
return ['minecraft.msg.motdbe.fail', [data.args[0], data.args[1]]];
|
|
85
|
-
const { ip, port, location, motd, gamemode, agreement, version, online, max, delay } = res.data;
|
|
86
|
-
return ['minecraft.msg.motdbe', [ip, port, location, motd, gamemode, agreement, version, online, max, delay]];
|
|
87
|
-
});
|
|
88
|
-
ctx
|
|
89
|
-
.command('mcskin <name>')
|
|
90
|
-
.action(async (data, session) => {
|
|
91
|
-
const res = mcskinSchema.parse(await ctx.http.get('https://api.hotaru.icu/api/mcskin', { name: data.args[0] }));
|
|
92
|
-
if (!res.data)
|
|
93
|
-
return ['minecraft.msg.mcskin.fail', [data.args[0]]];
|
|
94
|
-
return [
|
|
95
|
-
'minecraft.msg.mcskin',
|
|
96
|
-
[
|
|
97
|
-
data.args[0],
|
|
98
|
-
session.el.image(res.data.skin),
|
|
99
|
-
res.data.cape ? session.el.image(res.data.cape) : '',
|
|
100
|
-
res.data.avatar ? session.el.image(`base64://${res.data.avatar.substring(22)}`) : ''
|
|
101
|
-
]
|
|
102
|
-
];
|
|
80
|
+
const mcskinSchema = import_kotori_bot.Tsu.Object({
|
|
81
|
+
data: import_kotori_bot.Tsu.Union(
|
|
82
|
+
import_kotori_bot.Tsu.Null().optional(),
|
|
83
|
+
import_kotori_bot.Tsu.Object({
|
|
84
|
+
skin: import_kotori_bot.Tsu.String(),
|
|
85
|
+
cape: import_kotori_bot.Tsu.String().optional(),
|
|
86
|
+
avatar: import_kotori_bot.Tsu.String()
|
|
103
87
|
})
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'minecraft.msg.mcv',
|
|
116
|
-
[release, releaseDate, snapshot, snapshotDate, mcbe, session.i18n.date(new Date(mcbeDate))]
|
|
117
|
-
];
|
|
88
|
+
)
|
|
89
|
+
});
|
|
90
|
+
const mcvSchema1 = import_kotori_bot.Tsu.Object({
|
|
91
|
+
latest: import_kotori_bot.Tsu.Object({
|
|
92
|
+
release: import_kotori_bot.Tsu.String(),
|
|
93
|
+
snapshot: import_kotori_bot.Tsu.String()
|
|
94
|
+
}),
|
|
95
|
+
versions: import_kotori_bot.Tsu.Array(
|
|
96
|
+
import_kotori_bot.Tsu.Object({
|
|
97
|
+
id: import_kotori_bot.Tsu.String(),
|
|
98
|
+
releaseTime: import_kotori_bot.Tsu.String()
|
|
118
99
|
})
|
|
119
|
-
|
|
100
|
+
)
|
|
101
|
+
});
|
|
102
|
+
const mcvSchema2 = import_kotori_bot.Tsu.Array(
|
|
103
|
+
import_kotori_bot.Tsu.Object({
|
|
104
|
+
name: import_kotori_bot.Tsu.String(),
|
|
105
|
+
releaseDate: import_kotori_bot.Tsu.String().optional()
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
function main(ctx) {
|
|
109
|
+
ctx.command("motd <ip> [port:number=25565] - minecraft.descr.motd").action(async (data, session) => {
|
|
110
|
+
const res = motdSchema.parse(
|
|
111
|
+
await ctx.http.get("https://api.hotaru.icu/api/motd", { ip: data.args[0], port: data.args[1] })
|
|
112
|
+
);
|
|
113
|
+
if (res.data.status !== "online") return session.format("minecraft.msg.motd.fail", [data.args[0], data.args[1]]);
|
|
114
|
+
const { ip, port, location, motd, agreement, version, online, max, ping } = res.data;
|
|
115
|
+
const icon = typeof res.data.icon === "string" ? import_kotori_bot.Messages.image(`base64://${res.data.icon.substring(22)}`) : "";
|
|
116
|
+
return session.format("minecraft.msg.motd", [ip, port, location, motd, agreement, version, online, max, ping, icon]);
|
|
117
|
+
});
|
|
118
|
+
ctx.command("motdbe <ip> [port:number=19132] - minecraft.descr.motdbe").action(async (data, session) => {
|
|
119
|
+
const res = motdbeSchema.parse(
|
|
120
|
+
await ctx.http.get("https://api.hotaru.icu/api/motdpe", { ip: data.args[0], port: data.args[1] })
|
|
121
|
+
);
|
|
122
|
+
if (res.data.status !== "online") return session.format("minecraft.msg.motdbe.fail", [data.args[0], data.args[1]]);
|
|
123
|
+
const { ip, port, location, motd, gamemode, agreement, version, online, max, delay } = res.data;
|
|
124
|
+
const params = [ip, port, location, motd, gamemode, agreement, version, online, max, delay];
|
|
125
|
+
return session.format("minecraft.msg.motdbe", params);
|
|
126
|
+
});
|
|
127
|
+
ctx.command("mcskin <name>").action(async (data, session) => {
|
|
128
|
+
const res = mcskinSchema.parse(await ctx.http.get("https://api.hotaru.icu/api/mcskin", { name: data.args[0] }));
|
|
129
|
+
if (!res.data) return session.format("minecraft.msg.mcskin.fail", [data.args[0]]);
|
|
130
|
+
return session.format("minecraft.msg.mcskin", [
|
|
131
|
+
data.args[0],
|
|
132
|
+
import_kotori_bot.Messages.image(res.data.skin),
|
|
133
|
+
res.data.cape ? import_kotori_bot.Messages.image(res.data.cape) : "",
|
|
134
|
+
res.data.avatar ? import_kotori_bot.Messages.image(`base64://${res.data.avatar.substring(22)}`) : ""
|
|
135
|
+
]);
|
|
136
|
+
}).help("minecraft.descr.mcskin");
|
|
137
|
+
ctx.command("mcv").action(async (_, session) => {
|
|
138
|
+
const res = mcvSchema1.parse(await ctx.http.get("https://piston-meta.mojang.com/mc/game/version_manifest.json"));
|
|
139
|
+
const res2 = mcvSchema2.parse(await ctx.http.get("https://bugs.mojang.com/rest/api/2/project/10200/versions"));
|
|
140
|
+
const { release, snapshot } = res.latest;
|
|
141
|
+
const releaseDate = session.i18n.date(new Date(res.versions.find((el) => el.id === release)?.releaseTime ?? 0));
|
|
142
|
+
const snapshotDate = session.i18n.date(new Date(res.versions.find((el) => el.id === snapshot)?.releaseTime ?? 0));
|
|
143
|
+
const { name: mcbe, releaseDate: mcbeDate } = res2.find((el) => !!el.releaseDate) ?? {};
|
|
144
|
+
const params = [release, releaseDate, snapshot, snapshotDate, mcbe, session.i18n.date(new Date(mcbeDate ?? 0))];
|
|
145
|
+
return session.format("minecraft.msg.mcv", params);
|
|
146
|
+
}).help("minecraft.descr.mcv");
|
|
120
147
|
}
|
|
121
|
-
|
|
148
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
149
|
+
0 && (module.exports = {
|
|
150
|
+
lang,
|
|
151
|
+
main
|
|
152
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @Package kotori-plugin-minecraft
|
|
4
|
+
* @Version 1.0.2
|
|
5
|
+
* @Author Hotaru <me@hotaru.icu>
|
|
6
|
+
* @Copyright 2024 Hotaru. All rights reserved.
|
|
7
|
+
* @License GPL-3.0
|
|
8
|
+
* @Link https://github.com/kotorijs/kotori
|
|
9
|
+
* @Date 2024/8/8 20:54:12
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
"use strict";
|
|
13
|
+
var __create = Object.create;
|
|
14
|
+
var __defProp = Object.defineProperty;
|
|
15
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
16
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
17
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
18
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
+
mod
|
|
34
|
+
));
|
|
35
|
+
var import_node_dgram = __toESM(require("node:dgram"));
|
|
36
|
+
class MinecraftBedrockQuery {
|
|
37
|
+
host;
|
|
38
|
+
port;
|
|
39
|
+
constructor(host, port = 19132) {
|
|
40
|
+
this.host = host;
|
|
41
|
+
this.port = port;
|
|
42
|
+
}
|
|
43
|
+
async query() {
|
|
44
|
+
try {
|
|
45
|
+
return await this.queryDirect();
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async queryDirect() {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const client = import_node_dgram.default.createSocket("udp4");
|
|
53
|
+
const message = this.createUnconnectedPingPacket();
|
|
54
|
+
const timer = setTimeout(() => {
|
|
55
|
+
client.close();
|
|
56
|
+
reject(new Error("Query timed out"));
|
|
57
|
+
}, 5e3);
|
|
58
|
+
client.on("error", (err) => {
|
|
59
|
+
client.close();
|
|
60
|
+
reject(err);
|
|
61
|
+
});
|
|
62
|
+
client.on("message", (msg) => {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
client.close();
|
|
65
|
+
try {
|
|
66
|
+
const status = this.parseResponse(msg);
|
|
67
|
+
resolve(status);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
reject(error);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
client.send(message, this.port, this.host, (err) => {
|
|
73
|
+
if (err) {
|
|
74
|
+
client.close();
|
|
75
|
+
reject(err);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
createUnconnectedPingPacket() {
|
|
81
|
+
const packet = Buffer.alloc(1 + 8 + 8 + 16);
|
|
82
|
+
let offset = 0;
|
|
83
|
+
packet.writeUInt8(1, offset++);
|
|
84
|
+
packet.writeBigInt64BE(BigInt(Date.now()), offset);
|
|
85
|
+
offset += 8;
|
|
86
|
+
const magic = Buffer.from("00ffff00fefefefefdfdfdfd12345678", "hex");
|
|
87
|
+
magic.copy(packet, offset);
|
|
88
|
+
offset += 16;
|
|
89
|
+
packet.writeBigInt64BE(BigInt(2), offset);
|
|
90
|
+
return packet;
|
|
91
|
+
}
|
|
92
|
+
parseResponse(data) {
|
|
93
|
+
let offset = 25;
|
|
94
|
+
const serverInfoLength = data.readUInt16BE(offset);
|
|
95
|
+
offset += 2;
|
|
96
|
+
const serverInfo = data.slice(offset, offset + serverInfoLength).toString("utf8");
|
|
97
|
+
const res = serverInfo.split(";");
|
|
98
|
+
return {
|
|
99
|
+
motd: res[1],
|
|
100
|
+
levelName: res[7],
|
|
101
|
+
protocol: Number.parseInt(res[2], 10),
|
|
102
|
+
version: res[3],
|
|
103
|
+
currentPlayers: Number.parseInt(res[4], 10),
|
|
104
|
+
maxPlayers: Number.parseInt(res[5], 10),
|
|
105
|
+
serverGuid: res[6],
|
|
106
|
+
gameMode: res[8],
|
|
107
|
+
gameModeNumeric: Number.parseInt(res[9], 10),
|
|
108
|
+
port: Number.parseInt(res[10], 10)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function main() {
|
|
113
|
+
const query = new MinecraftBedrockQuery("192.168.1.7");
|
|
114
|
+
try {
|
|
115
|
+
const status = await query.query();
|
|
116
|
+
console.log(JSON.stringify(status, null, 2));
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error("Error querying server:", error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @Package kotori-plugin-minecraft
|
|
4
|
+
* @Version 1.0.2
|
|
5
|
+
* @Author Hotaru <me@hotaru.icu>
|
|
6
|
+
* @Copyright 2024 Hotaru. All rights reserved.
|
|
7
|
+
* @License GPL-3.0
|
|
8
|
+
* @Link https://github.com/kotorijs/kotori
|
|
9
|
+
* @Date 2024/8/8 20:54:12
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
"use strict";
|
|
13
|
+
var __create = Object.create;
|
|
14
|
+
var __defProp = Object.defineProperty;
|
|
15
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
16
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
17
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
18
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
+
mod
|
|
34
|
+
));
|
|
35
|
+
var import_node_net = __toESM(require("node:net"));
|
|
36
|
+
class MinecraftServerQuery {
|
|
37
|
+
host;
|
|
38
|
+
port;
|
|
39
|
+
constructor(host, port = 25565) {
|
|
40
|
+
this.host = host;
|
|
41
|
+
this.port = port;
|
|
42
|
+
}
|
|
43
|
+
async query() {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const socket = new import_node_net.default.Socket();
|
|
46
|
+
socket.on("error", (error) => {
|
|
47
|
+
reject(error);
|
|
48
|
+
});
|
|
49
|
+
socket.on("timeout", () => {
|
|
50
|
+
socket.destroy();
|
|
51
|
+
reject(new Error("Connection timed out"));
|
|
52
|
+
});
|
|
53
|
+
socket.connect(this.port, this.host, () => {
|
|
54
|
+
this.sendHandshake(socket).then(() => this.sendStatusRequest(socket)).then((status) => {
|
|
55
|
+
socket.destroy();
|
|
56
|
+
resolve(status);
|
|
57
|
+
}).catch((error) => {
|
|
58
|
+
socket.destroy();
|
|
59
|
+
reject(error);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
socket.setTimeout(5e3);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async sendHandshake(socket) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const handshakeBuffer = this.createHandshakePacket();
|
|
68
|
+
socket.write(handshakeBuffer, (err) => {
|
|
69
|
+
if (err) reject(new Error(`Failed to send handshake: ${err.message}`));
|
|
70
|
+
else resolve();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async sendStatusRequest(socket) {
|
|
75
|
+
return new Promise((resolve, reject) => {
|
|
76
|
+
const statusRequestBuffer = Buffer.from([1, 0]);
|
|
77
|
+
socket.write(statusRequestBuffer, (err) => {
|
|
78
|
+
if (err) reject(new Error(`Failed to send status request: ${err.message}`));
|
|
79
|
+
});
|
|
80
|
+
let responseData = Buffer.alloc(0);
|
|
81
|
+
socket.on("data", (data) => {
|
|
82
|
+
responseData = Buffer.concat([responseData, data]);
|
|
83
|
+
try {
|
|
84
|
+
const status = this.parseResponse(responseData);
|
|
85
|
+
resolve(status);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
reject(error);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
createHandshakePacket() {
|
|
93
|
+
const hostBuffer = Buffer.from(this.host, "utf8");
|
|
94
|
+
const packet = Buffer.alloc(10 + hostBuffer.length);
|
|
95
|
+
let offset = 0;
|
|
96
|
+
packet.writeInt8(0, offset++);
|
|
97
|
+
packet.writeInt8(71, offset++);
|
|
98
|
+
packet.writeInt8(hostBuffer.length, offset++);
|
|
99
|
+
hostBuffer.copy(packet, offset);
|
|
100
|
+
offset += hostBuffer.length;
|
|
101
|
+
packet.writeUInt16BE(this.port, offset);
|
|
102
|
+
offset += 2;
|
|
103
|
+
packet.writeInt8(1, offset++);
|
|
104
|
+
const packetLength = Buffer.alloc(1);
|
|
105
|
+
packetLength.writeInt8(packet.length);
|
|
106
|
+
return Buffer.concat([packetLength, packet]);
|
|
107
|
+
}
|
|
108
|
+
parseResponse(data) {
|
|
109
|
+
let offset = 0;
|
|
110
|
+
offset += 5;
|
|
111
|
+
const jsonLength = data.readInt32BE(offset);
|
|
112
|
+
offset += 4;
|
|
113
|
+
const jsonData = data.slice(offset, offset + jsonLength).toString("utf8");
|
|
114
|
+
return JSON.parse(jsonData);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function main() {
|
|
118
|
+
const query = new MinecraftServerQuery("mc.hypixel.net");
|
|
119
|
+
try {
|
|
120
|
+
const status = await query.query();
|
|
121
|
+
console.log(JSON.stringify(status, null, 2));
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error("Error querying server:", error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
main();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"minecraft.descr.motd": "MCJE server information inquiry",
|
|
3
|
+
"minecraft.descr.motdbe": "MCBE server information inquiry",
|
|
4
|
+
"minecraft.descr.mcskin": "MC legitimate account skin inquiry",
|
|
5
|
+
"minecraft.descr.mcv": "Inquiry of Minecraft version information",
|
|
6
|
+
"minecraft.msg.motd": "Status: Online\nIP: {0}\nPort: {1}\nPhysical Address: {2}\nMOTD: {3}\nProtocol Version: {4}\nGame Version: {5}\nOnline Players: {6} / {7}\nLatency: {8} ms\nIcon: {9}",
|
|
7
|
+
"minecraft.msg.motd.fail": "Status: Offline\nIP: {0}\nPort: {1}",
|
|
8
|
+
"minecraft.msg.motdbe": "Status: Online\nIP: {0}\nPort: {1}\nPhysical Address: {2}\nMOTD: {3}\nGame Mode: {4}\nProtocol Version: {5}\nGame Version: {6}\nOnline Players: {7} / {8}\nLatency: {9} ms",
|
|
9
|
+
"minecraft.msg.motdbe.fail": "Status: Offline\nIP: {0}\nPort: {1}",
|
|
10
|
+
"minecraft.msg.mcskin": "Player: {0}\nSkin: {1}\nCape: {2}\nHead: {3}",
|
|
11
|
+
"minecraft.msg.mcskin.fail": "No player found for {0}!",
|
|
12
|
+
"minecraft.msg.mcv": "Minecraft Java:\nLatest Version: {0}\nRelease Date: {1}\nLatest Snapshot: {2}\nRelease Date: {3}\nMinecraft Bedrock:\nLatest Version: {4}\nRelease Date: {5}"
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"minecraft.descr.motd": "MCJEサーバー情報の照会",
|
|
3
|
+
"minecraft.descr.motdbe": "MCBEサーバー情報の照会",
|
|
4
|
+
"minecraft.descr.mcskin": "MC正規アカウントのスキン照会",
|
|
5
|
+
"minecraft.descr.mcv": "Minecraftバージョン情報の照会",
|
|
6
|
+
"minecraft.msg.motd": "状態:オンライン\nIP:{0}\nポート:{1}\n物理アドレス:{2}\nMOTD:{3}\nプロトコルバージョン:{4}\nゲームバージョン:{5}\nオンライン人数:{6} / {7}\n遅延:{8} ms\nアイコン:{9}",
|
|
7
|
+
"minecraft.msg.motd.fail": "状態:オフライン\nIP:{0}\nポート:{1}",
|
|
8
|
+
"minecraft.msg.motdbe": "状態:オンライン\nIP:{0}\nポート:{1}\n物理アドレス:{2}\nMOTD:{3}\nゲームモード:{4}\nプロトコルバージョン:{5}\nゲームバージョン:{6}\nオンライン人数:{7} / {8}\n遅延: {9} ms",
|
|
9
|
+
"minecraft.msg.motdbe.fail": "状態:オフライン\nIP:{0}\nポート:{1}",
|
|
10
|
+
"minecraft.msg.mcskin": "プレイヤー:{0}\nスキン:{1}\nマント:{2}\n頭部:{3}",
|
|
11
|
+
"minecraft.msg.mcskin.fail": "{0}は存在しないプレイヤーです!",
|
|
12
|
+
"minecraft.msg.mcv": "MinecraftJava:\n最新版:{0}\nリリース日:{1}\n最新スナップショット:{2}\nリリース日:{3}\nMinecraftBedrock:\n最新版:{4}\nリリース日:{5}"
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"minecraft.descr.motd": "MCJE服務器信息查詢",
|
|
3
|
+
"minecraft.descr.motdbe": "MCBE服務器信息查詢",
|
|
4
|
+
"minecraft.descr.mcskin": "MC正版賬號皮膚查詢",
|
|
5
|
+
"minecraft.descr.mcv": "查詢Minecraft版本信息",
|
|
6
|
+
"minecraft.msg.motd": "狀態:在線\nIP:{0}\n端口:{1}\n物理地址:{2}\nMOTD:{3}\n協議版本:{4}\n遊戲版本:{5}\n在線人數:{6} / {7}\n延遲:{8} ms\n圖標:{9}",
|
|
7
|
+
"minecraft.msg.motd.fail": "狀態:離線\nIP:{0}\n端口:{1}",
|
|
8
|
+
"minecraft.msg.motdbe": "狀態:在線\nIP:{0}\n端口:{1}\n物理地址:{2}\nMOTD:{3}\n遊戲模式:{4}\n協議版本:{5}\n遊戲版本:{6}\n在線人數:{7} / {8}\n延遲: {9} ms",
|
|
9
|
+
"minecraft.msg.motdbe.fail": "狀態:離線\nIP:{0}\n端口:{1}",
|
|
10
|
+
"minecraft.msg.mcskin": "玩家:{0}\n皮膚:{1}\n披風:{2}\n頭顱:{3}",
|
|
11
|
+
"minecraft.msg.mcskin.fail": "{0}查無此人!",
|
|
12
|
+
"minecraft.msg.mcv": "MinecraftJava:\n最新版:{0}\n發布時間:{1}\n最新快照:{2}\n發布時間:{3}\nMinecraftBedrock:\n最新版:{4}\n發布時間:{5}"
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kotori-plugin-minecraft",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Plugin Of For Minecraft!",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"LICENSE",
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
|
-
"author": "Hotaru <
|
|
18
|
+
"author": "Hotaru <me@hotaru.icu>",
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"kotori-bot": "^1.
|
|
20
|
+
"kotori-bot": "^1.6.0-rc.1"
|
|
21
21
|
},
|
|
22
22
|
"kotori": {
|
|
23
23
|
"meta": {
|
|
@@ -28,8 +28,5 @@
|
|
|
28
28
|
"zh_CN"
|
|
29
29
|
]
|
|
30
30
|
}
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsc --build"
|
|
34
31
|
}
|
|
35
32
|
}
|