mc-beta-server/server/MPClient.ts

199 lines
6.6 KiB
TypeScript
Raw Normal View History

import { Console } from "hsconsole";
2023-06-22 12:43:28 +01:00
import { IReader } from "bufferstuff";
import { MinecraftServer } from "./MinecraftServer";
2023-04-10 21:52:30 +01:00
import { Packet } from "./enums/Packet";
import { PacketAnimation } from "./packets/Animation";
import { PacketChat } from "./packets/Chat"
import { PacketEntityAction } from "./packets/EntityAction";
2023-04-09 04:19:10 +01:00
import { PacketPlayer } from "./packets/Player";
import { PacketPlayerPosition } from "./packets/PlayerPosition";
import { PacketPlayerLook } from "./packets/PlayerLook";
import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook";
import { PacketPlayerDigging } from "./packets/PlayerDigging";
2023-04-09 04:19:10 +01:00
import { Player } from "./entities/Player";
import { Socket } from "net";
2023-04-10 14:42:14 +01:00
import { Vec3 } from "./Vec3";
2023-09-04 23:42:38 +01:00
import { PacketRespawn } from "./packets/Respawn";
import { PacketSpawnPosition } from "./packets/SpawnPosition";
2023-04-08 20:52:47 +01:00
export class MPClient {
2023-04-10 14:42:14 +01:00
private readonly mcServer:MinecraftServer;
2023-04-08 20:52:47 +01:00
private readonly socket:Socket;
2023-09-04 23:42:38 +01:00
public entity:Player;
2023-04-08 20:52:47 +01:00
2023-04-10 21:52:30 +01:00
private diggingAt:Vec3;
2023-04-10 14:42:14 +01:00
public constructor(mcServer:MinecraftServer, socket:Socket, entity:Player) {
this.mcServer = mcServer;
2023-04-08 20:52:47 +01:00
this.socket = socket;
this.entity = entity;
2023-04-10 21:52:30 +01:00
this.diggingAt = new Vec3();
2023-04-08 20:52:47 +01:00
}
2023-04-10 14:42:14 +01:00
private mapCoordsToFace(pos:Vec3, face:number) {
switch (face) {
case 0:
pos.y--;
return pos;
case 1:
pos.y++;
return pos;
case 2:
pos.z--;
return pos;
case 3:
pos.z++;
return pos;
case 4:
pos.x--;
return pos;
case 5:
pos.x++;
return pos;
}
}
public handlePacket(reader:IReader) {
2023-04-09 04:19:10 +01:00
const packetId = reader.readUByte();
switch (packetId) {
2023-04-10 21:52:30 +01:00
case Packet.Chat: this.handleChat(new PacketChat().readData(reader)); break;
case Packet.Player: this.handlePacketPlayer(new PacketPlayer().readData(reader)); break;
case Packet.PlayerPosition: this.handlePacketPlayerPosition(new PacketPlayerPosition().readData(reader)); break;
case Packet.PlayerLook: this.handlePacketPlayerLook(new PacketPlayerLook().readData(reader)); break;
case Packet.PlayerPositionLook: this.handlePacketPlayerPositionLook(new PacketPlayerPositionLook().readData(reader)); break;
case Packet.PlayerDigging: this.handlePacketPlayerDigging(new PacketPlayerDigging().readData(reader)); break;
//case Packets.PlayerBlockPlacement: break;
//case Packets.HoldingChange: break;
//case Packets.UseBed: break;
case Packet.Animation: this.handlePacketAnimation(new PacketAnimation().readData(reader)); break;
case Packet.EntityAction: this.handlePacketEntityAction(new PacketEntityAction().readData(reader)); break;
2023-08-20 01:18:05 +01:00
case Packet.DisconnectKick: this.handleDisconnectKick(); break;
2023-04-10 21:52:30 +01:00
default: Console.printWarn(`UNIMPLEMENTED PACKET: ${Packet[packetId]}`); break;
2023-04-09 04:19:10 +01:00
}
}
2023-04-10 14:42:14 +01:00
private handleChat(packet:PacketChat) {
2023-04-09 04:19:10 +01:00
const message = packet.message.split(" ");
2023-04-10 14:42:14 +01:00
if (message[0].startsWith("/")) {
packet.message = "";
if (message[0] === "/tp") {
2023-09-04 23:42:38 +01:00
const x = this.entity.x = parseFloat(message[1]);
const y = this.entity.y = parseFloat(message[2]);
const z = this.entity.z = parseFloat(message[3]);
this.send(new PacketPlayerPositionLook(x, y, y + 0.62, z, 0, 0, false).writeData());
2023-04-10 14:42:14 +01:00
Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`);
} else if (message[0] === "/csay") {
2023-08-20 01:18:05 +01:00
this.mcServer.sendChatMessage(`[CONSOLE] ${message.slice(1, message.length).join(" ")}`);
2023-04-17 02:05:11 +01:00
} else if (message[0] === "/top") {
packet.message = `Woosh!`;
const topBlock = this.entity.world.getChunk(this.entity.x >> 4, this.entity.z >> 4).getTopBlockY(this.entity.x & 0xf, this.entity.z & 0xf);
2023-08-20 01:18:05 +01:00
this.send(new PacketPlayerPosition(this.entity.x, topBlock + 3, topBlock + 3.62, this.entity.z, false).writeData());
2023-09-04 23:42:38 +01:00
} else if (message[0] === "/tpx") {
const dimension = parseInt(message[1]);
if (this.mcServer.worlds.has(dimension)) {
packet.message = "\u00a76Switching dimensions...";
this.switchDimension(dimension);
} else {
packet.message = `\u00a7cNo dimension by id "${dimension} exists!"`;
}
2023-04-10 14:42:14 +01:00
}
if (packet.message !== "") {
this.send(packet.writeData());
}
return;
2023-04-09 04:19:10 +01:00
}
2023-04-10 14:42:14 +01:00
packet.message = `<${this.entity.username}> ${packet.message}`;
Console.printInfo(`[CHAT] ${packet.message}`);
2023-04-10 14:42:14 +01:00
this.mcServer.sendToAllClients(packet.writeData());
2023-04-09 04:19:10 +01:00
}
2023-04-10 14:42:14 +01:00
private handlePacketPlayer(packet:PacketPlayer) {
2023-04-09 04:47:23 +01:00
this.entity.onGround = packet.onGround;
2023-04-09 04:19:10 +01:00
}
2023-04-10 14:42:14 +01:00
private handlePacketPlayerPosition(packet:PacketPlayerPosition) {
2023-04-09 04:19:10 +01:00
this.entity.x = packet.x;
this.entity.y = packet.y;
this.entity.z = packet.z;
}
2023-04-10 14:42:14 +01:00
private handlePacketPlayerLook(packet:PacketPlayerLook) {
2023-04-09 04:19:10 +01:00
this.entity.yaw = packet.yaw;
this.entity.pitch = packet.pitch;
}
2023-04-10 14:42:14 +01:00
private handlePacketPlayerPositionLook(packet:PacketPlayerPositionLook) {
2023-04-09 04:19:10 +01:00
this.entity.x = packet.x;
this.entity.y = packet.y;
this.entity.z = packet.z;
this.entity.yaw = packet.yaw;
this.entity.pitch = packet.pitch;
}
2023-04-10 21:52:30 +01:00
private handlePacketPlayerDigging(packet:PacketPlayerDigging) {
// Special drop item case
if (packet.status === 4) {
// TODO: Handle dropping items
return;
}
this.diggingAt.set(packet.x, packet.y, packet.z);
//this.mapCoordsToFace(this.diggingAt, packet.face);
if (packet.status === 0) {
// Started digging
} else if (packet.status === 2) {
if (this.entity.world.getBlockId(this.diggingAt.x, this.diggingAt.y, this.diggingAt.z) != 0) {
this.entity.world.setBlockWithNotify(this.diggingAt.x, this.diggingAt.y, this.diggingAt.z, 0);
2023-04-10 21:52:30 +01:00
}
}
}
// Animation start
private handlePacketAnimation(packet:PacketAnimation) {
// Forward this packet to all nearby clients
this.entity.world.sendToNearbyClients(this.entity, packet.writeData());
}
2023-04-10 14:42:14 +01:00
2023-04-10 21:52:30 +01:00
private handlePacketEntityAction(packet:PacketEntityAction) {
// Forward this packet to all nearby clients
switch (packet.action) {
case 1: this.entity.crouching = true; break;
case 2: this.entity.crouching = false; break;
case 3: break; // TODO: Leave Bed
}
2023-04-10 14:42:14 +01:00
}
2023-09-04 23:42:38 +01:00
private switchDimension(dimension:number) {
const world = this.mcServer.worlds.get(dimension);
if (world == undefined) {
return;
}
this.entity.world.removeEntity(this.entity);
this.entity.world = world;
world.addEntity(this.entity);
this.send(new PacketRespawn(dimension).writeData());
//this.send(new PacketSpawnPosition(8, 64, 8).writeData());
this.entity.x = 8;
this.entity.y = 70;
this.entity.z = 8;
this.send(new PacketPlayerPositionLook(8, 70, 70.62, 8, 0, 0, false).writeData());
this.entity.forceUpdatePlayerChunks();
}
2023-08-20 01:18:05 +01:00
private handleDisconnectKick() {
this.socket.end();
}
public send(buffer:Buffer) {
this.socket.write(buffer);
2023-04-08 20:52:47 +01:00
}
}