diff --git a/server/MPClient.ts b/server/MPClient.ts index 1ab85da..5eb99a0 100644 --- a/server/MPClient.ts +++ b/server/MPClient.ts @@ -7,17 +7,45 @@ import { PacketPlayerLook } from "./packets/PlayerLook"; import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook"; import { Player } from "./entities/Player"; import { PacketChat } from "./packets/Chat"; +import { MinecraftServer } from "./MinecraftServer"; +import { Vec3 } from "./Vec3"; +import { Console } from "../console"; export class MPClient { + private readonly mcServer:MinecraftServer; private readonly socket:Socket; public readonly entity:Player; - public constructor(socket:Socket, entity:Player) { + public constructor(mcServer:MinecraftServer, socket:Socket, entity:Player) { + this.mcServer = mcServer; this.socket = socket; this.entity = entity; } - handlePacket(reader:Reader) { + 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:Reader) { const packetId = reader.readUByte(); switch (packetId) { @@ -26,32 +54,51 @@ export class MPClient { case Packets.PlayerPosition: this.handlePacketPlayerPosition(new PacketPlayerPosition().readData(reader)); break; case Packets.PlayerLook: this.handlePacketPlayerLook(new PacketPlayerLook().readData(reader)); break; case Packets.PlayerPositionLook: this.handlePacketPlayerPositionLook(new PacketPlayerPositionLook().readData(reader)); break; + case Packets.PlayerDigging: this.handlePacketPlayerDigging(); break; } } - handleChat(packet:PacketChat) { + private handleChat(packet:PacketChat) { const message = packet.message.split(" "); - if (message[0] === "/tp") { - this.send(new PacketPlayerPositionLook(parseFloat(message[1]), parseFloat(message[2]), parseFloat(message[2]) + 0.62, parseFloat(message[3]), 0, 0, false).writeData()); + if (message[0].startsWith("/")) { + packet.message = ""; + if (message[0] === "/tp") { + this.send(new PacketPlayerPositionLook(parseFloat(message[1]), parseFloat(message[2]), parseFloat(message[2]) + 0.62, parseFloat(message[3]), 0, 0, false).writeData()); + Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`); + } else if (message[0] === "/csay") { + const consoleMessage = `[CONSOLE] ${message.slice(1, message.length).join(" ")}`; + Console.printChat(consoleMessage); + this.mcServer.sendToAllClients(new PacketChat(consoleMessage).writeData()); + } + + if (packet.message !== "") { + this.send(packet.writeData()); + } + + return; } + + packet.message = `<${this.entity.username}> ${packet.message}`; + Console.printChat(packet.message); + this.mcServer.sendToAllClients(packet.writeData()); } - handlePacketPlayer(packet:PacketPlayer) { + private handlePacketPlayer(packet:PacketPlayer) { this.entity.onGround = packet.onGround; } - handlePacketPlayerPosition(packet:PacketPlayerPosition) { + private handlePacketPlayerPosition(packet:PacketPlayerPosition) { this.entity.x = packet.x; this.entity.y = packet.y; this.entity.z = packet.z; } - handlePacketPlayerLook(packet:PacketPlayerLook) { + private handlePacketPlayerLook(packet:PacketPlayerLook) { this.entity.yaw = packet.yaw; this.entity.pitch = packet.pitch; } - handlePacketPlayerPositionLook(packet:PacketPlayerPositionLook) { + private handlePacketPlayerPositionLook(packet:PacketPlayerPositionLook) { this.entity.x = packet.x; this.entity.y = packet.y; this.entity.z = packet.z; @@ -59,7 +106,11 @@ export class MPClient { this.entity.pitch = packet.pitch; } - send(buffer:Buffer|Writer) { + private handlePacketPlayerDigging() { + + } + + public send(buffer:Buffer|Writer) { if (buffer instanceof Writer) { this.socket.write(buffer.toBuffer()); } else { diff --git a/server/MinecraftServer.ts b/server/MinecraftServer.ts index c903b9e..04f262b 100644 --- a/server/MinecraftServer.ts +++ b/server/MinecraftServer.ts @@ -1,6 +1,6 @@ import { Config } from "../config"; import { Console } from "../console"; -import { Server, Socket } from "net"; +import { Server, Socket, SocketAddress } from "net"; import { FunkyArray } from "../funkyArray"; import { World } from "./World"; import { Reader } from "../bufferStuff"; @@ -14,6 +14,7 @@ import { Player } from "./entities/Player"; import { PacketSpawnPosition } from "./packets/SpawnPosition"; import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook"; import { PacketChat } from "./packets/Chat"; +import { PacketNamedEntitySpawn } from "./packets/NamedEntitySpawn"; export class MinecraftServer { private static readonly PROTOCOL_VERSION = 14; @@ -112,7 +113,7 @@ export class MinecraftServer { const clientEntity = new Player(this, world, loginPacket.username); world.addEntity(clientEntity); - const client = new MPClient(socket, clientEntity); + const client = new MPClient(this, socket, clientEntity); setMPClient(client); clientEntity.mpClient = client; this.clients.set(loginPacket.username, client); @@ -122,6 +123,14 @@ export class MinecraftServer { socket.write(new PacketLoginRequest(clientEntity.entityId, "", 0, 0).writeData()); socket.write(new PacketSpawnPosition(8, 64, 8).writeData()); + const thisPlayerSpawn = new PacketNamedEntitySpawn(clientEntity.entityId, clientEntity.username, clientEntity.absX, clientEntity.absY, clientEntity.absZ, clientEntity.absYaw, clientEntity.absPitch, 0).writeData(); + world.players.forEach(player => { + if (player.entityId !== clientEntity.entityId && clientEntity.distanceTo(player) < World.ENTITY_MAX_SEND_DISTANCE) { + socket.write(new PacketNamedEntitySpawn(player.entityId, player.username, player.absX, player.absY, player.absZ, player.absYaw, player.absPitch, 0).writeData()); + player.mpClient?.send(thisPlayerSpawn); + } + }); + socket.write(new PacketPlayerPositionLook(8, 70, 70.62, 8, 0, 0, false).writeData()); } else { socket.write(new PacketDisconnectKick("Failed to find world to put player in.").writeData()); diff --git a/server/Vec3.ts b/server/Vec3.ts new file mode 100644 index 0000000..7670f24 --- /dev/null +++ b/server/Vec3.ts @@ -0,0 +1,19 @@ +export class Vec3 { + public x:number; + public y:number; + public z:number; + + public constructor(x?:number, y?:number, z?:number) { + if (typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number") { + this.x = x; + this.y = y; + this.z = z; + } else if (typeof(x) === "number" && typeof(y) !== "number" && typeof(z) !== "number") { + this.x = x; + this.y = x; + this.z = x; + } else { + this.x = this.y = this.z = 0; + } + } +} \ No newline at end of file diff --git a/server/World.ts b/server/World.ts index 051f9ea..5775772 100644 --- a/server/World.ts +++ b/server/World.ts @@ -7,19 +7,26 @@ import { HillyGenerator } from "./generators/Hilly"; import { IGenerator } from "./generators/IGenerator"; export class World { + public static ENTITY_MAX_SEND_DISTANCE = 50; + public chunks:FunkyArray; public entites:FunkyArray; + public players:FunkyArray; public generator:IGenerator; public constructor(seed:number) { this.chunks = new FunkyArray(); this.entites = new FunkyArray(); + this.players = new FunkyArray(); this.generator = new HillyGenerator(seed); } public addEntity(entity:IEntity) { this.entites.set(entity.entityId, entity); + if (entity instanceof Player) { + this.players.set(entity.entityId, entity); + } } // TODO: getChunkByCoordPair failed in here during removeEntity, figure out why. @@ -33,6 +40,7 @@ export class World { this.unloadChunk(coordPair); } } + this.players.remove(entity.entityId); } this.entites.remove(entity.entityId); @@ -53,6 +61,14 @@ export class World { return existingChunk; } + public sendToNearbyClients(sentFrom:IEntity, buffer:Buffer) { + this.players.forEach(player => { + if (sentFrom.entityId !== player.entityId && Math.abs(sentFrom.distanceTo(player)) < World.ENTITY_MAX_SEND_DISTANCE) { + player.mpClient?.send(buffer); + } + }); + } + public getChunkByCoordPair(coordPair:number) { const existingChunk = this.chunks.get(coordPair); if (!(existingChunk instanceof Chunk)) { @@ -69,6 +85,8 @@ export class World { public tick() { this.entites.forEach(entity => { + entity.onTick(); + if (entity instanceof Player) { if (entity.justUnloaded.length > 0) { for (const coordPair of entity.justUnloaded) { @@ -82,8 +100,6 @@ export class World { entity.justUnloaded = new Array(); } } - - entity.onTick(); }) } } \ No newline at end of file diff --git a/server/entities/Entity.ts b/server/entities/Entity.ts index f45c0f3..5319197 100644 --- a/server/entities/Entity.ts +++ b/server/entities/Entity.ts @@ -21,6 +21,14 @@ export class Entity implements IEntity { this.x = this.y = this.z = this.lastX = this.lastY = this.lastZ = 0; } + distanceTo(entity:IEntity) { + const dX = entity.x - this.x, + dY = entity.y - this.y, + dZ = entity.z - this.z; + + return Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2) + Math.pow(dZ, 2)); + } + onTick() { this.lastX = this.x; this.lastY = this.y; diff --git a/server/entities/EntityLiving.ts b/server/entities/EntityLiving.ts index c5dfe3c..60dc051 100644 --- a/server/entities/EntityLiving.ts +++ b/server/entities/EntityLiving.ts @@ -1,20 +1,79 @@ import { World } from "../World"; +import { PacketEntityLook } from "../packets/EntityLook"; +import { PacketEntityLookRelativeMove } from "../packets/EntityLookRelativeMove"; +import { PacketEntityRelativeMove } from "../packets/EntityRelativeMove"; +import { PacketEntityTeleport } from "../packets/EntityTeleport"; import { Entity } from "./Entity"; export class EntityLiving extends Entity { public yaw:number; + public lastYaw:number; public pitch:number; + public lastPitch:number; public onGround:boolean; + public absX:number; + public absY:number; + public absZ:number; + public absYaw:number; + public absPitch:number; + public lastAbsX:number; + public lastAbsY:number; + public lastAbsZ:number; + public lastAbsYaw:number; + public lastAbsPitch:number; + public constructor(world:World) { super(world); - this.yaw = 0; - this.pitch = 0; + this.yaw = this.lastYaw = this.pitch = this.lastPitch = this.absX = this.absY = this.absZ = this.absYaw = this.absPitch = this.lastAbsX = this.lastAbsY = this.lastAbsZ = this.lastAbsYaw = this.lastAbsPitch = 0; this.onGround = false; } + private constrainRot(rot:number) { + return Math.min(Math.max(rot, -128), 127); + } + + private sendPositionUpdate() { + this.absX = Math.floor(this.x * 32); + this.absY = Math.floor(this.y * 32); + this.absZ = Math.floor(this.z * 32); + // This is suuuuuper jank + this.absYaw = this.constrainRot(Math.floor(((this.yaw - 180 >= 0 ? this.yaw - 180 : (this.yaw - 180) % 360 + 360) % 360 / 360) * 256) - 128); + this.absPitch = this.constrainRot(Math.floor((this.pitch % 360 * 256) / 360)); + const diffX = this.absX - this.lastAbsX; + const diffY = this.absY - this.lastAbsY; + const diffZ = this.absZ - this.lastAbsZ; + const diffYaw = this.absYaw - this.lastAbsYaw; + const diffPitch = this.absPitch - this.lastAbsPitch; + + const doRelativeMove = Math.abs(diffX) >= 5 || Math.abs(diffY) >= 5 || Math.abs(diffZ) >= 5; + const doLook = Math.abs(diffYaw) >= 5 || Math.abs(diffPitch) >= 5; + if (Math.abs(diffX) > 128 || Math.abs(diffY) > 128 || Math.abs(diffZ) > 128) { + this.world.sendToNearbyClients(this, new PacketEntityTeleport(this.entityId, this.absX, this.absY, this.absZ, this.absYaw, this.absPitch).writeData()); + } else if (doRelativeMove && doLook) { + this.world.sendToNearbyClients(this, new PacketEntityLookRelativeMove(this.entityId, diffX, diffY, diffZ, this.absYaw, this.absPitch).writeData()); + } else if (doRelativeMove) { + this.world.sendToNearbyClients(this, new PacketEntityRelativeMove(this.entityId, diffX, diffY, diffZ).writeData()); + } else if (doLook) { + this.world.sendToNearbyClients(this, new PacketEntityLook(this.entityId, this.absYaw, this.absPitch).writeData()); + } + + if (doRelativeMove) { + this.lastAbsX = this.absX; + this.lastAbsY = this.absY; + this.lastAbsZ = this.absZ; + } + if (doLook) { + this.lastAbsYaw = this.absYaw; + this.lastAbsPitch = this.absPitch; + } + } + onTick() { super.onTick(); + this.sendPositionUpdate(); + this.lastYaw = this.yaw; + this.lastPitch = this.lastPitch; } } \ No newline at end of file diff --git a/server/entities/IEntity.ts b/server/entities/IEntity.ts index 8c46ce2..722ca48 100644 --- a/server/entities/IEntity.ts +++ b/server/entities/IEntity.ts @@ -6,5 +6,6 @@ export interface IEntity { lastX:number, lastY:number, lastZ:number, + distanceTo:(entity:IEntity) => number, onTick:() => void } \ No newline at end of file diff --git a/server/entities/Player.ts b/server/entities/Player.ts index 42a963a..48b7d5c 100644 --- a/server/entities/Player.ts +++ b/server/entities/Player.ts @@ -33,6 +33,7 @@ export class Player extends EntityLiving { if (bitX != this.lastX >> 4 || bitZ != this.lastZ >> 4 || this.firstUpdate) { if (this.firstUpdate) { this.firstUpdate = false; + // TODO: Make this based on the player's coords this.mpClient?.send(new PacketPreChunk(0, 0, true).writeData()); const chunk = this.world.getChunk(0, 0); (async () => { diff --git a/server/enums/Packets.ts b/server/enums/Packets.ts index 4e1e5a7..ffaba34 100644 --- a/server/enums/Packets.ts +++ b/server/enums/Packets.ts @@ -13,9 +13,22 @@ export enum Packets { PlayerPosition = 0x0B, PlayerLook = 0x0C, PlayerPositionLook = 0x0D, + PlayerDigging = 0x0E, + PlayerBlockPlacement = 0x0F, + HoldingChange = 0x10, + UseBed = 0x11, + Animation = 0x12, + EntityAction = 0x13, + NamedEntitySpawn = 0x14, PreChunk = 0x32, MapChunk = 0x33, - DisconnectKick = 255 + Entity = 0x1E, + EntityRelativeMove = 0x1F, + EntityLook = 0x20, + EntityLookRelativeMove = 0x21, + EntityTeleport = 0x22, + + DisconnectKick = 0xff } \ No newline at end of file diff --git a/server/generators/Hilly.ts b/server/generators/Hilly.ts index 27570c9..2bc51ab 100644 --- a/server/generators/Hilly.ts +++ b/server/generators/Hilly.ts @@ -34,7 +34,6 @@ export class HillyGenerator implements IGenerator { // This is good enough (and fast enough) for what is needed here. private mulberry32(a:number) { return function() { - // TODO: Determine if "a" is needed let t = a += 0x6D2B79F5; t = Math.imul(t ^ t >>> 15, t | 1); t ^= t + Math.imul(t ^ t >>> 7, t | 61); @@ -87,6 +86,14 @@ export class HillyGenerator implements IGenerator { chunk.setBlock(Block.wood.blockId, x, tY, z); tY++; } + chunk.setBlock(Block.leaves.blockId, x - 1, tY - 2, z); + chunk.setBlock(Block.leaves.blockId, x + 1, tY - 2, z); + chunk.setBlock(Block.leaves.blockId, x, tY - 2, z - 1); + chunk.setBlock(Block.leaves.blockId, x, tY - 2, z + 1); + chunk.setBlock(Block.leaves.blockId, x - 2, tY - 2, z); + chunk.setBlock(Block.leaves.blockId, x + 2, tY - 2, z); + chunk.setBlock(Block.leaves.blockId, x, tY - 2, z - 2); + chunk.setBlock(Block.leaves.blockId, x, tY - 2, z + 2); } } } diff --git a/server/packets/Entity.ts b/server/packets/Entity.ts new file mode 100644 index 0000000..86d7f7d --- /dev/null +++ b/server/packets/Entity.ts @@ -0,0 +1,26 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketEntity implements IPacket { + public packetId = Packets.Entity; + public entityId:number; + + public constructor(entityId?:number) { + if (typeof(entityId) == "number") { + this.entityId = entityId; + } else { + this.entityId = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + + return this; + } + + public writeData() { + return new Writer(5).writeUByte(this.packetId).writeInt(this.entityId).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/EntityLook.ts b/server/packets/EntityLook.ts new file mode 100644 index 0000000..90b5e3e --- /dev/null +++ b/server/packets/EntityLook.ts @@ -0,0 +1,34 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketEntityLook implements IPacket { + public packetId = Packets.EntityLook; + public entityId:number; + public yaw:number; + public pitch:number; + + public constructor(entityId?:number, yaw?:number, pitch?:number) { + if (typeof(entityId) == "number" && typeof(yaw) === "number" && typeof(pitch) === "number") { + this.entityId = entityId; + this.yaw = yaw; + this.pitch = pitch; + } else { + this.entityId = Number.MIN_VALUE; + this.yaw = Number.MIN_VALUE; + this.pitch = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + this.yaw = reader.readByte(); + this.pitch = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(7).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.yaw).writeByte(this.pitch).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/EntityLookRelativeMove.ts b/server/packets/EntityLookRelativeMove.ts new file mode 100644 index 0000000..b868900 --- /dev/null +++ b/server/packets/EntityLookRelativeMove.ts @@ -0,0 +1,46 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketEntityLookRelativeMove implements IPacket { + public packetId = Packets.EntityLookRelativeMove; + public entityId:number; + public dX:number; + public dY:number; + public dZ:number; + public yaw:number; + public pitch:number; + + public constructor(entityId?:number, dX?:number, dY?:number, dZ?:number, yaw?:number, pitch?:number) { + if (typeof(entityId) == "number" && typeof(dX) === "number" && typeof(dY) === "number" && typeof(dZ) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number") { + this.entityId = entityId; + this.dX = dX; + this.dY = dY; + this.dZ = dZ; + this.yaw = yaw; + this.pitch = pitch; + } else { + this.entityId = Number.MIN_VALUE; + this.dX = Number.MIN_VALUE; + this.dY = Number.MIN_VALUE; + this.dZ = Number.MIN_VALUE; + this.yaw = Number.MIN_VALUE; + this.pitch = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + this.dX = reader.readByte(); + this.dY = reader.readByte(); + this.dZ = reader.readByte(); + this.yaw = reader.readByte(); + this.pitch = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(10).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.dX).writeByte(this.dY).writeByte(this.dZ).writeByte(this.yaw).writeByte(this.pitch).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/EntityRelativeMove.ts b/server/packets/EntityRelativeMove.ts new file mode 100644 index 0000000..cc99eb9 --- /dev/null +++ b/server/packets/EntityRelativeMove.ts @@ -0,0 +1,38 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketEntityRelativeMove implements IPacket { + public packetId = Packets.EntityRelativeMove; + public entityId:number; + public dX:number; + public dY:number; + public dZ:number; + + public constructor(entityId?:number, dX?:number, dY?:number, dZ?:number) { + if (typeof(entityId) == "number" && typeof(dX) === "number" && typeof(dY) === "number" && typeof(dZ) === "number") { + this.entityId = entityId; + this.dX = dX; + this.dY = dY; + this.dZ = dZ; + } else { + this.entityId = Number.MIN_VALUE; + this.dX = Number.MIN_VALUE; + this.dY = Number.MIN_VALUE; + this.dZ = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + this.dX = reader.readByte(); + this.dY = reader.readByte(); + this.dZ = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(8).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.dX).writeByte(this.dY).writeByte(this.dZ).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/EntityTeleport.ts b/server/packets/EntityTeleport.ts new file mode 100644 index 0000000..e1f9c8a --- /dev/null +++ b/server/packets/EntityTeleport.ts @@ -0,0 +1,46 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketEntityTeleport implements IPacket { + public packetId = Packets.EntityTeleport; + public entityId:number; + public x:number; + public y:number; + public z:number; + public yaw:number; + public pitch:number; + + public constructor(entityId?:number, x?:number, y?:number, z?:number, yaw?:number, pitch?:number) { + if (typeof(entityId) == "number" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number") { + this.entityId = entityId; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } else { + this.entityId = Number.MIN_VALUE; + this.x = Number.MIN_VALUE; + this.y = Number.MIN_VALUE; + this.z = Number.MIN_VALUE; + this.yaw = Number.MIN_VALUE; + this.pitch = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + this.x = reader.readInt(); + this.y = reader.readInt(); + this.z = reader.readInt(); + this.yaw = reader.readByte(); + this.pitch = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(19).writeUByte(this.packetId).writeInt(this.entityId).writeInt(this.x).writeInt(this.y).writeInt(this.z).writeByte(this.yaw).writeByte(this.pitch).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/NamedEntitySpawn.ts b/server/packets/NamedEntitySpawn.ts new file mode 100644 index 0000000..07498b9 --- /dev/null +++ b/server/packets/NamedEntitySpawn.ts @@ -0,0 +1,53 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketNamedEntitySpawn implements IPacket { + public packetId = Packets.NamedEntitySpawn; + public entityId:number; + public playerName:string; + public x:number; + public y:number; + public z:number; + public yaw:number; + public pitch:number; + public currentItem:number; + + public constructor(entityId?:number, playerName?:string, x?:number, y?:number, z?:number, yaw?:number, pitch?:number, currentItem?:number) { + if (typeof(entityId) === "number" && typeof(playerName) === "string" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number" && typeof(currentItem) === "number") { + this.entityId = entityId; + this.playerName = playerName; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + this.currentItem = currentItem; + } else { + this.entityId = Number.MIN_VALUE; + this.playerName = ""; + this.x = Number.MIN_VALUE; + this.y = Number.MIN_VALUE; + this.z = Number.MIN_VALUE; + this.yaw = Number.MIN_VALUE; + this.pitch = Number.MIN_VALUE; + this.currentItem = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.entityId = reader.readInt(); + this.playerName = reader.readString(); + this.x = reader.readInt(); + this.y = reader.readInt(); + this.z = reader.readInt(); + this.yaw = reader.readByte(); + this.pitch = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(23 + this.playerName.length * 2).writeUByte(this.packetId).writeInt(this.entityId).writeString(this.playerName).writeInt(this.x).writeInt(this.y).writeInt(this.z).writeByte(this.yaw).writeByte(this.pitch).writeShort(this.currentItem).toBuffer(); + } +} \ No newline at end of file diff --git a/server/packets/PlayerDigging.ts b/server/packets/PlayerDigging.ts new file mode 100644 index 0000000..fc852ba --- /dev/null +++ b/server/packets/PlayerDigging.ts @@ -0,0 +1,42 @@ +import { Reader, Writer } from "../../bufferStuff"; +import { Packets } from "../enums/Packets"; +import { IPacket } from "./IPacket"; + +export class PacketPlayerDigging implements IPacket { + public packetId = Packets.PlayerDigging; + public status:number; + public x:number; + public y:number; + public z:number; + public face:number; + + public constructor(status?:number, x?:number, y?:number, z?:number, face?:number) { + if (typeof(status) == "number" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(face) === "number") { + this.status = status; + this.x = x; + this.y = y; + this.z = z; + this.face = face; + } else { + this.status = Number.MIN_VALUE; + this.x = Number.MIN_VALUE; + this.y = Number.MIN_VALUE; + this.z = Number.MIN_VALUE; + this.face = Number.MIN_VALUE; + } + } + + public readData(reader:Reader) { + this.status = reader.readByte(); + this.x = reader.readInt(); + this.y = reader.readByte(); + this.z = reader.readInt(); + this.face = reader.readByte(); + + return this; + } + + public writeData() { + return new Writer(12).writeUByte(this.packetId).writeByte(this.status).writeInt(this.x).writeByte(this.y).writeInt(this.z).writeByte(this.face).toBuffer(); + } +} \ No newline at end of file