touch ups, translate UUIDS

This commit is contained in:
q13x 2023-07-05 12:51:23 -07:00
parent 9f6b0d5692
commit 006aac1b3f
8 changed files with 222 additions and 214 deletions

185
package-lock.json generated
View File

@ -17,6 +17,7 @@
"chalk": "^5.2.0",
"dotenv": "^16.0.3",
"minecraft-protocol": "^1.40.2",
"node-fetch": "^3.3.1",
"parse-domain": "^7.0.1",
"prismarine-block": "^1.16.3",
"prismarine-chunk": "^1.33.0",
@ -1060,6 +1061,25 @@
"node": ">=14"
}
},
"node_modules/minecraft-protocol/node_modules/node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/minecraft-protocol/node_modules/readable-stream": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz",
@ -1174,23 +1194,20 @@
}
},
"node_modules/node-fetch": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz",
"integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==",
"license": "MIT",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
"integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
"dependencies": {
"whatwg-url": "^5.0.0"
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "4.x || >=6.0.0"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/node-rsa": {
@ -1224,24 +1241,6 @@
"parse-domain-update": "bin/update.js"
}
},
"node_modules/parse-domain/node_modules/node-fetch": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
"integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
"license": "MIT",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/prebuild-install": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
@ -1283,6 +1282,25 @@
"uuid-1345": "^1.0.2"
}
},
"node_modules/prismarine-auth/node_modules/node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/prismarine-biome": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/prismarine-biome/-/prismarine-biome-1.3.0.tgz",
@ -1362,6 +1380,25 @@
"node-fetch": "^2.6.1"
}
},
"node_modules/prismarine-realms/node_modules/node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/prismarine-registry": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/prismarine-registry/-/prismarine-registry-1.6.0.tgz",
@ -1650,8 +1687,7 @@
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/tslib": {
"version": "2.5.0",
@ -1727,14 +1763,12 @@
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@ -1787,6 +1821,25 @@
"node-fetch": "^2.6.1",
"uuid": "^8.2.0"
}
},
"node_modules/yggdrasil/node_modules/node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
}
},
"dependencies": {
@ -2384,6 +2437,14 @@
"yggdrasil": "^1.4.0"
},
"dependencies": {
"node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"readable-stream": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz",
@ -2460,11 +2521,13 @@
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
},
"node-fetch": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz",
"integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
"integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
"requires": {
"whatwg-url": "^5.0.0"
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
}
},
"node-rsa": {
@ -2490,18 +2553,6 @@
"requires": {
"is-ip": "^4.0.0",
"node-fetch": "^3.2.0"
},
"dependencies": {
"node-fetch": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
"integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
"requires": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
}
}
}
},
"prebuild-install": {
@ -2535,6 +2586,16 @@
"node-fetch": "^2.6.1",
"smart-buffer": "^4.1.0",
"uuid-1345": "^1.0.2"
},
"dependencies": {
"node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"requires": {
"whatwg-url": "^5.0.0"
}
}
}
},
"prismarine-biome": {
@ -2606,6 +2667,16 @@
"requires": {
"debug": "^4.3.3",
"node-fetch": "^2.6.1"
},
"dependencies": {
"node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"requires": {
"whatwg-url": "^5.0.0"
}
}
}
},
"prismarine-registry": {
@ -2888,6 +2959,16 @@
"requires": {
"node-fetch": "^2.6.1",
"uuid": "^8.2.0"
},
"dependencies": {
"node-fetch": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"requires": {
"whatwg-url": "^5.0.0"
}
}
}
}
}

View File

@ -17,6 +17,7 @@
"chalk": "^5.2.0",
"dotenv": "^16.0.3",
"minecraft-protocol": "^1.40.2",
"node-fetch": "^3.3.1",
"parse-domain": "^7.0.1",
"prismarine-block": "^1.16.3",
"prismarine-chunk": "^1.33.0",

View File

@ -15,8 +15,7 @@ export async function getTokenProfileEasyMc(token: string): Promise<object> {
);
const resJson = await res.json();
if (resJson.error)
throw new Error(Enums.ChatColor.RED + `EasyMC: ${resJson.error}`);
if (resJson.error) throw new Error(Enums.ChatColor.RED + `${resJson.error}`);
if (!resJson)
throw new Error(
Enums.ChatColor.RED + "EasyMC replied with an empty response!?"
@ -43,66 +42,3 @@ export async function getTokenProfileEasyMc(token: string): Promise<object> {
},
};
}
async function easyMcAuth(client, options) {
const fetchOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: options.easyMcToken,
}),
};
try {
const res = await fetch(
"https://api.easymc.io/v1/token/redeem",
fetchOptions
);
const resJson = await res.json();
if (resJson.error)
throw new Error(Enums.ChatColor.RED + `EasyMC: ${resJson.error}`);
if (!resJson)
throw new Error(
Enums.ChatColor.RED + "EasyMC replied with an empty response!?"
);
if (
resJson.session?.length !== 43 ||
resJson.mcName?.length < 3 ||
resJson.uuid?.length !== 36
)
throw new Error(
Enums.ChatColor.RED + "Invalid response from EasyMC received!"
);
const session = {
accessToken: resJson.session,
selectedProfile: {
name: resJson.mcName,
id: resJson.uuid,
},
};
options.haveCredentials = true;
client.session = session;
options.username = client.username = session.selectedProfile.name;
options.accessToken = session.accessToken;
client.emit("session", session);
} catch (error) {
client.emit("error", error);
return;
}
options.connect(client);
}
function getEasyMcClientOptions(token: string) {
if (token.length !== 20) {
throw new Error(
Enums.ChatColor.RED +
"EasyMC authentication requires an alt token. See https://easymc.io/get ."
);
}
return {
auth: easyMcAuth,
easyMcToken: token,
sessionServer: "https://sessionserver.easymc.io",
username: Buffer.alloc(0),
};
}

View File

@ -1,10 +1,26 @@
import metadata from "./metadata.json" assert { type: "json" };
import { config } from "./config.js";
import { createServer } from "minecraft-protocol";
import { ClientState, ConnectionState, ServerGlobals } from "./types.js";
import { handleConnect, hushConsole, setSG } from "./utils.js";
import path from "path";
import { readFileSync } from "fs";
const PluginManager = PLUGIN_MANAGER;
const metadata = JSON.parse(
readFileSync(
process.platform == "win32"
? path
.join(
path.dirname(new URL(import.meta.url).pathname),
"metadata.json"
)
.slice(1)
: path.join(
path.dirname(new URL(import.meta.url).pathname),
"metadata.json"
)
).toString()
);
const Logger = PluginManager.Logger;
const Enums = PluginManager.Enums;

View File

@ -487,6 +487,9 @@ export async function onConnect(client: ClientState) {
},
],
});
logger.info(
`Player ${client.gameClient.username} is attempting to connect to ${host}:${port} under their Minecraft account's username (${savedAuth.selectedProfile.name}) using online mode!`
);
const player = PLUGIN_MANAGER.proxy.players.get(
client.gameClient.username
);
@ -785,6 +788,9 @@ export async function onConnect(client: ClientState) {
},
],
});
logger.info(
`Player ${client.gameClient.username} is attempting to connect to ${host}:${port} under their EasyMC alt token's username (${appendOptions.username}) using EasyMC mode!`
);
const player = PLUGIN_MANAGER.proxy.players.get(
client.gameClient.username
);
@ -903,10 +909,8 @@ export async function onConnect(client: ClientState) {
},
],
});
sendCustomMessage(
client.gameClient,
"Attempting to switch servers, please wait... (if you don't get connected to the target server for a while, the server might be online only)",
"gray"
logger.info(
`Player ${client.gameClient.username} is attempting to connect to ${host}:${port} under their Eaglercraft username (${client.gameClient.username}) using offline mode!`
);
const player = PLUGIN_MANAGER.proxy.players.get(
client.gameClient.username

View File

@ -17,103 +17,51 @@ export namespace BungeeUtil {
static readonly CAST_UUID_CLIENT: string[] = ["spectate"];
private _logger: Logger;
private _serverSerializer: any;
private _clientSerializer: any;
private _clientDeserializer: any;
private _serverDeserializer: any;
constructor(ssPlayerUUID: string, csPlayerUUID: string) {
this.serverSidePlayerUUID = ssPlayerUUID;
this.clientSidePlayerUUID = csPlayerUUID;
this._logger = new Logger("PacketTranslator");
this._serverSerializer = createSerializer({
state: states.PLAY,
isServer: true,
version: "1.8.8",
customPackets: null,
});
this._clientSerializer = createSerializer({
state: states.PLAY,
isServer: false,
version: "1.8.8",
customPackets: null,
});
this._clientDeserializer = createDeserializer({
state: states.PLAY,
isServer: false,
version: "1.8.8",
customPackets: null,
});
this._serverDeserializer = createDeserializer({
state: states.PLAY,
isServer: true,
version: "1.8.8",
customPackets: null,
});
}
public onClientWrite(packet: Buffer): Buffer /* write to server */ {
const { name, params } =
this._serverDeserializer.parsePacketBuffer(packet).data;
return this._clientSerializer.createPacketBuffer(
this._translatePacketClient(params, { name })
);
}
public onServerWrite(packet: any, meta: any): Buffer /* write to client */ {
return this._serverSerializer.createPacketBuffer(
this._translatePacketServer(packet, meta)
);
}
private _translatePacketClient(packet: any, meta: any): any | null {
if (PacketUUIDTranslator.CAST_UUID_CLIENT.some((id) => id == meta.name)) {
if (meta.name == "spectate") {
if (packet.target == this.clientSidePlayerUUID) {
packet.target = this.serverSidePlayerUUID;
} else if (packet.target == this.serverSidePlayerUUID) {
packet.target = this.clientSidePlayerUUID;
}
public translatePacketClient(packet: any, meta: any): [string, object] {
if (meta.name == "spectate") {
if (packet.target == this.clientSidePlayerUUID) {
packet.target = this.serverSidePlayerUUID;
} else if (packet.target == this.serverSidePlayerUUID) {
packet.target = this.clientSidePlayerUUID;
}
}
return {
name: meta.name,
params: packet,
};
return [meta.name, packet];
}
private _translatePacketServer(packet: any, meta: any): any | null {
if (PacketUUIDTranslator.CAST_UUID_SERVER.some((id) => id == meta.name)) {
if (meta.name == "update_attributes") {
for (const prop of packet.properties) {
for (const modifier of prop.modifiers) {
if (modifier.uuid == this.serverSidePlayerUUID) {
modifier.uuid = this.clientSidePlayerUUID;
} else if (modifier.uuid == this.clientSidePlayerUUID) {
modifier.uuid = this.serverSidePlayerUUID;
}
}
}
} else if (meta.name == "named_entity_spawn") {
if (packet.playerUUID == this.serverSidePlayerUUID) {
packet.playerUUID = this.clientSidePlayerUUID;
} else if (packet.playerUUID == this.clientSidePlayerUUID) {
packet.playerUUID = this.serverSidePlayerUUID;
}
} else if (meta.name == "player_info") {
for (const player of packet.data) {
if (player.UUID == this.serverSidePlayerUUID) {
player.UUID = this.clientSidePlayerUUID;
} else if (player.UUID == this.clientSidePlayerUUID) {
player.UUID = this.serverSidePlayerUUID;
public translatePacketServer(packet: any, meta: any): [string, object] {
if (meta.name == "update_attributes") {
for (const prop of packet.properties) {
for (const modifier of prop.modifiers) {
if (modifier.uuid == this.serverSidePlayerUUID) {
modifier.uuid = this.clientSidePlayerUUID;
} else if (modifier.uuid == this.clientSidePlayerUUID) {
modifier.uuid = this.serverSidePlayerUUID;
}
}
}
} else if (meta.name == "named_entity_spawn") {
if (packet.playerUUID == this.serverSidePlayerUUID) {
packet.playerUUID = this.clientSidePlayerUUID;
} else if (packet.playerUUID == this.clientSidePlayerUUID) {
packet.playerUUID = this.serverSidePlayerUUID;
}
} else if (meta.name == "player_info") {
for (const player of packet.data) {
if (player.UUID == this.serverSidePlayerUUID) {
player.UUID = this.clientSidePlayerUUID;
} else if (player.UUID == this.clientSidePlayerUUID) {
player.UUID = this.serverSidePlayerUUID;
}
}
}
return {
name: meta.name,
params: packet,
};
return [meta.name, packet];
}
}

View File

@ -15,7 +15,8 @@ import { MineProtocol } from "./Protocol.js";
import { EaglerSkins } from "./skins/EaglerSkins.js";
import { Util } from "./Util.js";
import { BungeeUtil } from "./BungeeUtil.js";
import { ConnectionState } from "../plugins/EagProxyAAS/types";
import { ConnectionState } from "../plugins/EagProxyAAS/types.js";
import { SCSyncUuidPacket } from "./packets/SCSyncUuidPacket.js";
const { createSerializer, createDeserializer } = pkg;
@ -30,6 +31,8 @@ export class Player extends EventEmitter {
private _switchingServers: boolean = false;
private _logger: Logger;
private _alreadyConnected: boolean = false;
public translator?: BungeeUtil.PacketUUIDTranslator;
public serializer: any;
public deserializer: any;
private _kickMessage: string;
@ -97,10 +100,16 @@ export class Player extends EventEmitter {
}
} else {
try {
const packetData = {
...this.deserializer.parsePacketBuffer(msg)?.data,
cancel: false,
};
const parsed = this.deserializer.parsePacketBuffer(msg)?.data,
translated = this.translator.translatePacketClient(
parsed.params,
parsed.name
),
packetData = {
name: translated[0],
params: translated[1],
cancel: false,
};
this.emit("vanillaPacket", packetData, "CLIENT", this);
if (!packetData.cancel) {
(this as any)._sendPacketToServer(msg);
@ -323,6 +332,10 @@ export class Player extends EventEmitter {
if (!stream) {
if (switchingServers) {
if (meta.name == "login" && meta.state == states.PLAY && uuid) {
this.translator = new BungeeUtil.PacketUUIDTranslator(
client.uuid,
this.uuid
);
const pckSeq = BungeeUtil.getRespawnSequence(
packet,
this.serializer
@ -346,6 +359,10 @@ export class Player extends EventEmitter {
}
} else {
if (meta.name == "login" && meta.state == states.PLAY && uuid) {
this.translator = new BungeeUtil.PacketUUIDTranslator(
client.uuid,
this.uuid
);
this.ws.send(
this.serializer.createPacketBuffer({
name: "login",
@ -364,11 +381,15 @@ export class Player extends EventEmitter {
}
}
} else {
const eventData = {
name: meta.name,
params: packet,
cancel: false,
};
const translated = this.translator!.translatePacketServer(
packet,
meta.name
),
eventData = {
name: translated[0],
params: translated[1],
cancel: false,
};
this.emit("vanillaPacket", eventData, "SERVER", this);
if (!eventData.cancel) {
this.ws.send(

View File

@ -8,6 +8,7 @@ import { Player } from "../Player.js";
import { CSChannelMessagePacket } from "../packets/channel/CSChannelMessage.js";
import { SCChannelMessagePacket } from "../packets/channel/SCChannelMessage.js";
import { Logger } from "../../logger.js";
import fetch from "node-fetch";
// TODO: convert all functions to use MineProtocol's UUID manipulation functions