implement packet compression, implement player controller, implement join server authentication, add cobblestone, implement chunk provider, implement block position, implement session, implement movement, chunk, chat and block update packets, version 1.1.5

This commit is contained in:
LabyStudio
2022-06-19 14:25:40 +02:00
parent 2e42d482ed
commit 7266a89f5a
67 changed files with 11831 additions and 2761 deletions
@@ -1,10 +1,13 @@
import ByteBuf from "./util/ByteBuf.js";
import PacketRegistry from "./PacketRegistry.js";
import ProtocolState from "./ProtocolState.js";
import {aesjs} from "../../../../../../libraries/aes.js";
import {require} from "../../../../Start.js";
export default class NetworkManager {
static DEBUG = false;
static MAX_COMPRESSION = 2097152;
constructor(minecraft) {
this.minecraft = minecraft;
this.socket = null;
@@ -14,10 +17,10 @@ export default class NetworkManager {
this.registry = new PacketRegistry();
this.protocolState = ProtocolState.HANDSHAKE;
this.readBuffer = new ByteBuf();
this.expectedLength = -1;
this.queue = [];
this.pako = require("pako");
this.compressionThreshold = 0;
}
setNetworkHandler(networkHandler) {
@@ -41,11 +44,10 @@ export default class NetworkManager {
this.connected = true;
// Send proxy handshake
let object = {
"address": this.address,
this.sendProxyPacket(0, {
"host": this.address,
"port": this.port,
};
this.socket.send(JSON.stringify(object));
});
// Handle connect event
this.networkHandler.onConnect();
@@ -54,6 +56,14 @@ export default class NetworkManager {
this.flushPacketQueue();
}
sendProxyPacket(id, payload) {
let object = {
"id": id,
"payload": payload
};
this.socket.send(JSON.stringify(object));
}
sendPacket(packet) {
if (this.connected) {
this._sendPacketImmediately(packet);
@@ -67,81 +77,138 @@ export default class NetworkManager {
let packetState = this.registry.getPacketState(packet);
if (packetState !== this.protocolState) {
if (packetState === null) {
console.error("[Network] Tried to send unknown packet: " + packet);
console.error("[Network] Tried to send unknown packet: " + packet.constructor.name);
return;
}
console.log("[Network] Switching protocol state from " + ProtocolState.getName(this.protocolState) + " to " + ProtocolState.getName(packetState));
this.protocolState = packetState;
this.setState(packetState);
}
// Write packet to buffer
// Packet Codec
let buffer = new ByteBuf();
buffer.writeByte(this.registry.getClientBoundPacketId(this.protocolState, packet));
packet.write(buffer);
buffer.setPosition(0);
// Write chunk header
let array = buffer.getArray();
// Packet Compression
if (this.compressionThreshold !== 0) {
let length = buffer.length();
if (length > this.compressionThreshold) {
let compressed = this.pako.deflate(buffer.getArray(), {
chunkSize: 8192
});
buffer = new ByteBuf();
buffer.writeVarInt(length);
buffer.write(compressed);
} else {
let copy = buffer.getArray();
buffer = new ByteBuf();
buffer.writeVarInt(0);
buffer.write(copy);
}
buffer.setPosition(0);
}
// Packet Sizer
let wrapper = new ByteBuf();
wrapper.writeVarInt(array.length);
wrapper.write(array);
let chunk = wrapper.getArray().buffer;
wrapper.writeVarInt(buffer.length());
wrapper.write(buffer.getArray());
// Encrypt chunk
// Packet Compression
if (this.isEncrypted) {
chunk = this.encryption.encrypt(new Uint8Array(chunk));
wrapper = new ByteBuf(this.encryption.encrypt(wrapper.getArray()));
}
// Send chunk
this.socket.send(chunk);
this.socket.send(wrapper.getArray());
console.log("[Network] [OUT] " + packet.constructor.name);
if (NetworkManager.DEBUG) {
console.log("[Network] [OUT] " + packet.constructor.name);
}
}
_onMessage(event) {
let chunk = new Int8Array(event.data);
try {
let data = new Uint8Array(event.data);
// Decrypt chunk
if (this.isEncrypted) {
chunk = this.encryption.decrypt(new Uint8Array(event.data));
}
// Packet Compression
if (this.isEncrypted) {
data = this.decryption.decrypt(data);
}
// Read packet header
if (this.expectedLength === -1) {
let buf = new ByteBuf(chunk);
this.expectedLength = buf.readVarInt(); // Read packet length
this.readBuffer.setPosition(0);
chunk = chunk.slice(buf.getPosition());
}
// Packet Sizer
let bufferIn = new ByteBuf(new Int8Array(data));
while (bufferIn.readableBytes() > 0) {
let three = [0, 0, 0];
for (let i = 0; i < three.length; i++) {
three[i] = bufferIn.readByte();
if (three[i] >= 0) {
let length = new ByteBuf(three).readVarInt();
if (length === 0) {
throw new Error("Empty Packet!");
}
// Fill packet content
this.readBuffer.write(chunk);
// Handle packet
if (this.readBuffer.getPosition() >= this.expectedLength) {
this.expectedLength = -1;
this.readBuffer.setPosition(0);
this.onPacketBufferReceived(this.readBuffer);
if (bufferIn.readableBytes() < length) {
break;
} else {
this.handlePacket(new ByteBuf(bufferIn.getSlicedArray(length)));
bufferIn.skipBytes(length);
}
break;
}
}
}
} catch (e) {
console.error(e);
}
}
onPacketBufferReceived(buffer) {
handlePacket(buffer) {
// Packet Compression
if (this.compressionThreshold !== 0) {
let uncompressedLength = buffer.readVarInt();
if (uncompressedLength !== 0) {
if (uncompressedLength < this.compressionThreshold) {
throw new Error("Badly compressed packet - size of " + uncompressedLength + " is below server threshold of " + this.compressionThreshold);
}
if (uncompressedLength > NetworkManager.MAX_COMPRESSION) {
throw new Error("Badly compressed packet - size of " + uncompressedLength + " is larger than protocol maximum of " + NetworkManager.MAX_COMPRESSION);
}
// Decompress
buffer = new ByteBuf(this.pako.inflate(new Uint8Array(buffer.getSlicedArray()), {
chunkSize: 8192
}));
if (buffer.length() !== uncompressedLength) {
throw new Error("Badly compressed packet - decompressed size of " + buffer.length() + " is not equal to original size of " + uncompressedLength);
}
}
}
// Packet Codec
let packetId = buffer.readByte(); // Read packet id
let clazz = this.registry.getServerBoundById(this.protocolState, packetId);
if (clazz === null) {
console.log("[Network] Unknown packet id: " + packetId);
if (NetworkManager.DEBUG) {
console.log("[Network] [IN] Unknown packet id: " + packetId + " (0x" + packetId.toString(16) + ")");
}
return;
} else {
if (NetworkManager.DEBUG) {
console.log("[Network] [IN] " + clazz.name);
}
}
let packet = new clazz;
console.log("[Network] [IN] " + packet.constructor.name);
packet.read(buffer, buffer.length);
packet.handle(this.networkHandler);
}
_onError(event) {
console.error("[Network] Error: " + event.data);
}
_onClose(event) {
@@ -164,6 +231,26 @@ export default class NetworkManager {
enableEncryption(secretKey) {
this.isEncrypted = true;
this.encryption = new aesjs.ModeOfOperation.cfb(secretKey, secretKey, 1);
this.decryption = new (require("aesjs").ModeOfOperation).cfb(secretKey, secretKey, 1);
this.encryption = new (require("aesjs").ModeOfOperation).cfb(secretKey, secretKey, 1);
}
setState(packetState) {
console.log("[Network] Switching protocol state from " + this.protocolState.getName() + " to " + packetState.getName());
this.protocolState = packetState;
}
getState() {
return this.protocolState;
}
setCompressionThreshold(threshold) {
console.log("[Network] Set compression threshold to " + threshold);
if (threshold >= 0) {
this.compressionThreshold = threshold;
} else {
this.compressionThreshold = 0;
}
}
}