From 19a131bd9435af94477727d09bd93380a003acaa Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Mon, 20 Jun 2022 03:16:20 +0200 Subject: [PATCH] implement player spawning, movement, animation, metadata and destroying, implement NBT serialization, version 1.1.7 --- README.md | 4 + src/js/net/minecraft/client/Minecraft.js | 14 +- src/js/net/minecraft/client/entity/Entity.js | 80 ++++++++-- .../minecraft/client/entity/EntityLiving.js | 42 ++++- .../minecraft/client/entity/PlayerEntity.js | 145 ++++++------------ .../client/entity/PlayerEntityMultiplayer.js | 101 +++++++++++- .../client/network/NetworkManager.js | 3 +- .../client/network/PacketRegistry.js | 28 ++++ .../network/controller/PlayerController.js | 2 +- .../controller/PlayerControllerMultiplayer.js | 5 +- .../network/handler/NetworkPlayHandler.js | 111 +++++++++++++- .../client/ClientConfirmTransactionPacket.js | 18 +++ .../play/client/ClientPlayerStatePacket.js | 26 ++++ .../play/client/ClientSwingArmPacket.js | 8 + .../play/server/ServerAnimationPacket.js | 35 +++++ .../server/ServerConfirmTransactionPacket.js | 34 ++++ .../server/ServerDestroyEntitiesPacket.js | 25 +++ .../play/server/ServerEntityHeadLookPacket.js | 28 ++++ .../play/server/ServerEntityMetadataPacket.js | 28 ++++ .../play/server/ServerEntityMovementPacket.js | 71 +++++++++ .../play/server/ServerEntityPositionPacket.js | 10 ++ .../ServerEntityPositionRotationPacket.js | 11 ++ .../play/server/ServerEntityRotationPacket.js | 10 ++ .../play/server/ServerEntityTeleportPacket.js | 61 ++++++++ .../play/server/ServerSpawnPlayerPacket.js | 75 +++++++++ .../minecraft/client/network/util/ByteBuf.js | 75 +++++++++ .../render/entity/entity/PlayerRenderer.js | 10 +- src/js/net/minecraft/client/world/Chunk.js | 2 +- src/js/net/minecraft/client/world/World.js | 17 +- src/js/net/minecraft/nbt/NBTIO.js | 29 ++++ src/js/net/minecraft/nbt/tag/TagRegistry.js | 61 ++++++++ .../minecraft/nbt/tag/builtin/ByteArrayTag.js | 28 ++++ .../net/minecraft/nbt/tag/builtin/ByteTag.js | 26 ++++ .../minecraft/nbt/tag/builtin/CompoundTag.js | 41 +++++ .../minecraft/nbt/tag/builtin/DoubleTag.js | 26 ++++ .../net/minecraft/nbt/tag/builtin/FloatTag.js | 26 ++++ .../minecraft/nbt/tag/builtin/IntArrayTag.js | 32 ++++ .../net/minecraft/nbt/tag/builtin/IntTag.js | 26 ++++ .../net/minecraft/nbt/tag/builtin/ListTag.js | 54 +++++++ .../net/minecraft/nbt/tag/builtin/LongTag.js | 26 ++++ .../net/minecraft/nbt/tag/builtin/ShortTag.js | 26 ++++ .../minecraft/nbt/tag/builtin/StringTag.js | 31 ++++ src/js/net/minecraft/nbt/tag/builtin/Tag.js | 17 ++ src/js/net/minecraft/util/MissingPackets.js | 91 +++++++++++ 44 files changed, 1481 insertions(+), 138 deletions(-) create mode 100644 src/js/net/minecraft/client/network/packet/play/client/ClientConfirmTransactionPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/client/ClientPlayerStatePacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/client/ClientSwingArmPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerAnimationPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerConfirmTransactionPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerDestroyEntitiesPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityHeadLookPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityMetadataPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityMovementPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionRotationPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityRotationPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerEntityTeleportPacket.js create mode 100644 src/js/net/minecraft/client/network/packet/play/server/ServerSpawnPlayerPacket.js create mode 100644 src/js/net/minecraft/nbt/NBTIO.js create mode 100644 src/js/net/minecraft/nbt/tag/TagRegistry.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/ByteArrayTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/ByteTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/CompoundTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/DoubleTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/FloatTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/IntArrayTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/IntTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/ListTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/LongTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/ShortTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/StringTag.js create mode 100644 src/js/net/minecraft/nbt/tag/builtin/Tag.js create mode 100644 src/js/net/minecraft/util/MissingPackets.js diff --git a/README.md b/README.md index b4a78cf..4fb2cd5 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Click [here](https://labystudio.de/page/minecraft/) for a demo! - World - 16x16x16 Chunks - Block type, data, sky & block lightning + - Entities - Minecraft Alpha Generator - 64 bits seed - Perlin terrain generation @@ -73,12 +74,14 @@ Click [here](https://labystudio.de/page/minecraft/) for a demo! - Hot-Bar - Chat - Debug + - Player list - Multiplayer - Networking - RSA Encryption - AES Encryption - Compression - Splitting + - NBT Serialization - Sub-Protocols - Handshake - Status @@ -89,6 +92,7 @@ Click [here](https://labystudio.de/page/minecraft/) for a demo! - Movement Packets - Block Update Packets - Chat Packets + - Player Packets - Commands - /help - /time diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index 2aea1c1..1e8df89 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -26,7 +26,7 @@ import PlayerControllerMultiplayer from "./network/controller/PlayerControllerMu export default class Minecraft { - static VERSION = "1.1.6" + static VERSION = "1.1.7" static URL_GITHUB = "https://github.com/labystudio/js-minecraft"; static PROTOCOL_VERSION = 47; //758; @@ -124,6 +124,7 @@ export default class Minecraft { if (this.world !== null) { this.world.getChunkProvider().getChunks().clear(); + this.world.clearEntities(); this.world = null; this.player = null; this.loadingScreen = null; @@ -135,6 +136,14 @@ export default class Minecraft { this.loadingScreen.setTitle("Building terrain..."); this.displayScreen(this.loadingScreen); + // Clear previous world + if (this.world !== null) { + this.world.getChunkProvider().getChunks().clear(); + this.world.clearEntities(); + this.worldRenderer.reset(); + this.itemRenderer.reset(); + } + // Create world this.world = world; this.worldRenderer.scene.add(this.world.group); @@ -277,9 +286,6 @@ export default class Minecraft { // Tick renderer this.worldRenderer.onTick(); - // Tick the player - this.player.onUpdate(); - // Tick particle renderer this.particleRenderer.onTick(); } diff --git a/src/js/net/minecraft/client/entity/Entity.js b/src/js/net/minecraft/client/entity/Entity.js index 7c292dc..1b0db08 100644 --- a/src/js/net/minecraft/client/entity/Entity.js +++ b/src/js/net/minecraft/client/entity/Entity.js @@ -4,9 +4,11 @@ import Random from "../../util/Random.js"; export default class Entity { - constructor(minecraft, world) { + constructor(minecraft, world, id) { this.minecraft = minecraft; this.world = world; + this.id = id; + this.random = new Random(); this.renderer = null; @@ -24,7 +26,6 @@ export default class Entity { this.stepHeight = 0.0; this.onGround = false; - this.sneaking = false; this.rotationYaw = 0; this.rotationPitch = 0; @@ -43,6 +44,12 @@ export default class Entity { this.ticksExisted = 0; this.isDead = false; + this.serverPositionX = 0; + this.serverPositionY = 0; + this.serverPositionZ = 0; + + this.metaData = {}; + this.boundingBox = new BoundingBox(); this.setPosition(this.x, this.y, this.z); } @@ -70,19 +77,36 @@ export default class Entity { y + this.height, z + width ); - - this.motionX = 0; - this.motionY = 0; - this.motionZ = 0; - - this.prevX = this.x; - this.prevY = this.y; - this.prevZ = this.z; } setRotation(yaw, pitch) { - this.rotationYaw = yaw; - this.rotationPitch = pitch; + this.rotationYaw = yaw % 360; + this.rotationPitch = pitch % 360; + } + + setTargetPositionAndRotation(x, y, z, yaw, pitch, increments) { + this.setPosition(x, y, z); + this.setRotation(yaw, pitch); + } + + setPositionAndRotation(x, y, z, yaw, pitch) { + this.prevX = this.x = x; + this.prevY = this.y = y; + this.prevZ = this.z = z; + + this.prevRotationYaw = this.rotationYaw = yaw; + this.prevRotationPitch = this.rotationPitch = pitch; + + let diffYaw = (this.prevRotationYaw - yaw); + if (diffYaw < -180) { + this.prevRotationYaw += 360; + } + if (diffYaw >= 180) { + this.prevRotationYaw -= 360; + } + + this.setPosition(this.x, this.y, this.z); + this.setRotation(yaw, pitch); } onUpdate() { @@ -119,7 +143,7 @@ export default class Entity { let originalTargetY = targetY; let originalTargetZ = targetZ; - if (this.onGround && this.sneaking) { + if (this.onGround && this.isSneaking()) { for (; targetX !== 0.0 && this.world.getCollisionBoxes(this.boundingBox.offset(targetX, -this.stepHeight, 0.0)).length === 0; originalTargetX = targetX) { if (targetX < 0.05 && targetX >= -0.05) { targetX = 0.0; @@ -214,4 +238,34 @@ export default class Entity { || this.rotationPitch !== this.prevRotationPitch; } + isSneaking() { + return this.getFlag(1); + } + + setSneaking(sneaking) { + this.setFlag(1, sneaking); + } + + updateMetaData(metaData) { + for (const [id, value] of Object.entries(metaData)) { + this.metaData[value.id] = value; + } + } + + getFlag(flag) { + return typeof this.metaData[0] !== "undefined" && (this.metaData[0].value & 1 << flag) !== 0; + } + + setFlag(flag, value) { + if (typeof this.metaData[0] === "undefined") { + this.metaData[0] = {id: 0, type: 0, value: 0}; + } + + if (value) { + this.metaData[0].value |= 1 << flag; + } else { + this.metaData[0].value &= ~(1 << flag); + } + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/entity/EntityLiving.js b/src/js/net/minecraft/client/entity/EntityLiving.js index 20bd189..68495cd 100644 --- a/src/js/net/minecraft/client/entity/EntityLiving.js +++ b/src/js/net/minecraft/client/entity/EntityLiving.js @@ -3,8 +3,8 @@ import MathHelper from "../../util/MathHelper.js"; export default class EntityLiving extends Entity { - constructor(minecraft, world) { - super(minecraft, world); + constructor(minecraft, world, id) { + super(minecraft, world, id); this.jumpTicks = 0; @@ -70,6 +70,28 @@ export default class EntityLiving extends Entity { --this.jumpTicks; } + if (this.rotationPositionIncrements > 0) { + // Interpolate the position and rotation + let x = this.x + (this.targetX - this.x) / this.rotationPositionIncrements; + let y = this.y + (this.targetY - this.y) / this.rotationPositionIncrements; + let z = this.z + (this.targetZ - this.z) / this.rotationPositionIncrements; + + // Update yaw and pitch + let yaw = MathHelper.wrapAngleTo180(this.targetYaw - this.rotationYaw); + this.rotationYaw = this.rotationYaw + yaw / this.rotationPositionIncrements; + this.rotationPitch = (this.rotationPitch + (this.targetPitch - this.rotationPitch) / this.rotationPositionIncrements); + + // Decrement position increments + this.rotationPositionIncrements--; + + // Update position + this.setPosition(x, y, z); + this.setRotation(this.rotationYaw, this.rotationPitch); + } + + // TODO Find the right spot to update this + this.rotationYawHead = this.rotationYaw; + // Stop if too slow if (Math.abs(this.motionX) < 0.003) { this.motionX = 0.0; @@ -81,8 +103,6 @@ export default class EntityLiving extends Entity { this.motionZ = 0.0; } - this.rotationYawHead = this.rotationYaw; - // Jump if (this.jumping) { if (this.isInWater()) { @@ -174,6 +194,15 @@ export default class EntityLiving extends Entity { } } + setTargetPositionAndRotation(x, y, z, yaw, pitch, increments) { + this.targetX = x; + this.targetY = y; + this.targetZ = z; + this.targetYaw = yaw; + this.targetPitch = pitch; + this.rotationPositionIncrements = increments; + } + swingArm() { let swingAnimationEnd = 6; if (!this.isSwingInProgress || this.swingProgressInt >= swingAnimationEnd / 2 || this.swingProgressInt < 0) { @@ -217,4 +246,9 @@ export default class EntityLiving extends Entity { return value - wrapped; } + setRotationYawHead(yaw) { + this.targetYaw = yaw; // TODO should be rotationYawHead + // this.rotationYawHead = yaw; + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/entity/PlayerEntity.js b/src/js/net/minecraft/client/entity/PlayerEntity.js index b37dac9..f650293 100644 --- a/src/js/net/minecraft/client/entity/PlayerEntity.js +++ b/src/js/net/minecraft/client/entity/PlayerEntity.js @@ -10,8 +10,8 @@ export default class PlayerEntity extends EntityLiving { static name = "PlayerEntity"; - constructor(minecraft, world) { - super(minecraft, world); + constructor(minecraft, world, id) { + super(minecraft, world, id); this.inventory = new InventoryPlayer(); this.username = "Player"; @@ -73,73 +73,7 @@ export default class PlayerEntity extends EntityLiving { } onLivingUpdate() { - this.prevCameraYaw = this.cameraYaw; - this.prevCameraPitch = this.cameraPitch; - - if (this.sprintToggleTimer > 0) { - --this.sprintToggleTimer; - } - if (this.flyToggleTimer > 0) { - --this.flyToggleTimer; - } - - let prevMoveForward = this.moveForward; - let prevJumping = this.jumping; - - this.updateKeyboardInput(); - - // Toggle jumping - if (!prevJumping && this.jumping) { - if (this.flyToggleTimer === 0) { - this.flyToggleTimer = 7; - } else { - this.flying = !this.flying; - this.flyToggleTimer = 0; - - this.updateFOVModifier(); - } - } - - // Toggle sprint - if (prevMoveForward === 0 && this.moveForward > 0) { - if (this.sprintToggleTimer === 0) { - this.sprintToggleTimer = 7; - } else { - this.sprinting = true; - this.sprintToggleTimer = 0; - - this.updateFOVModifier(); - } - } - - if (this.sprinting && (this.moveForward <= 0 || this.collision || this.sneaking)) { - this.sprinting = false; - - this.updateFOVModifier(); - } - super.onLivingUpdate(); - - this.jumpMovementFactor = this.speedInAir; - - if (this.sprinting) { - this.jumpMovementFactor = this.jumpMovementFactor + this.speedInAir * 0.3; - } - - let speedXZ = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); - let speedY = (Math.atan(-this.motionY * 0.2) * 15.0); - - if (speedXZ > 0.1) { - speedXZ = 0.1; - } - if (!this.onGround || this.health <= 0.0) { - speedXZ = 0.0; - } - if (this.onGround || this.health <= 0.0) { - speedY = 0.0; - } - this.cameraYaw += (speedXZ - this.cameraYaw) * 0.4; - this.cameraPitch += (speedY - this.cameraPitch) * 0.8; } isInWater() { @@ -167,7 +101,7 @@ export default class PlayerEntity extends EntityLiving { travelFlying(forward, vertical, strafe) { // Fly move up and down - if (this.sneaking) { + if (this.isSneaking()) { this.moveStrafing = strafe / 0.3; this.moveForward = forward / 0.3; this.motionY -= this.flySpeed * 3.0; @@ -205,40 +139,42 @@ export default class PlayerEntity extends EntityLiving { } travel(forward, vertical, strafe) { - let prevSlipperiness = this.getBlockSlipperiness() * 0.91; + let isSlow = this.onGround && this.isSneaking(); let prevX = this.x; let prevZ = this.z; - let isSlow = this.onGround && this.sneaking; + if (this === this.world.minecraft.player) { + let prevSlipperiness = this.getBlockSlipperiness() * 0.91; - let value = 0.16277136 / (prevSlipperiness * prevSlipperiness * prevSlipperiness); - let friction; + let value = 0.16277136 / (prevSlipperiness * prevSlipperiness * prevSlipperiness); + let friction; - if (this.onGround) { - friction = this.getAIMoveSpeed() * value; - } else { - friction = this.jumpMovementFactor; + if (this.onGround) { + friction = this.getAIMoveSpeed() * value; + } else { + friction = this.jumpMovementFactor; + } + + this.moveRelative(forward, vertical, strafe, friction); + + // Get new speed + let slipperiness = this.getBlockSlipperiness() * 0.91; + + // Move + this.collision = this.moveCollide(-this.motionX, this.motionY, -this.motionZ); + + // Gravity + if (!this.flying) { + this.motionY -= 0.08; + } + + // Decrease motion + this.motionX *= slipperiness; + this.motionY *= 0.98; + this.motionZ *= slipperiness; } - this.moveRelative(forward, vertical, strafe, friction); - - // Get new speed - let slipperiness = this.getBlockSlipperiness() * 0.91; - - // Move - this.collision = this.moveCollide(-this.motionX, this.motionY, -this.motionZ); - - // Gravity - if (!this.flying) { - this.motionY -= 0.08; - } - - // Decrease motion - this.motionX *= slipperiness; - this.motionY *= 0.98; - this.motionZ *= slipperiness; - // Step sound if (!isSlow) { let blockX = MathHelper.floor(this.x); @@ -254,11 +190,13 @@ export default class PlayerEntity extends EntityLiving { this.nextStepDistance = this.distanceWalked + 1; let block = Block.getById(typeId); - let sound = block.getSound(); + if (block !== null) { + let sound = block.getSound(); - // Play sound - if (!block.isLiquid()) { - this.minecraft.soundManager.playSound(sound.getStepSound(), this.x, this.y, this.z, 0.15, sound.getPitch()); + // Play sound + if (!block.isLiquid()) { + this.minecraft.soundManager.playSound(sound.getStepSound(), this.x, this.y, this.z, 0.15, sound.getPitch()); + } } } } @@ -324,7 +262,7 @@ export default class PlayerEntity extends EntityLiving { jumping = true; } if (Keyboard.isKeyDown(this.minecraft.settings.keySprinting)) { - if (this.moveForward > 0 && !this.sneaking && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) { + if (this.moveForward > 0 && !this.isSneaking() && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) { this.sprinting = true; this.updateFOVModifier(); @@ -344,11 +282,11 @@ export default class PlayerEntity extends EntityLiving { this.moveStrafing = moveStrafe; this.jumping = jumping; - this.sneaking = sneaking; + this.setSneaking(sneaking); } getEyeHeight() { - return this.sneaking ? 1.50 : 1.62; + return this.isSneaking() ? 1.50 : 1.62; } updateFOVModifier() { @@ -429,4 +367,7 @@ export default class PlayerEntity extends EntityLiving { return this.world.rayTraceBlocks(from, to); } + isSprinting() { + return this.sprinting; + } } \ No newline at end of file diff --git a/src/js/net/minecraft/client/entity/PlayerEntityMultiplayer.js b/src/js/net/minecraft/client/entity/PlayerEntityMultiplayer.js index 25749e1..9341ff7 100644 --- a/src/js/net/minecraft/client/entity/PlayerEntityMultiplayer.js +++ b/src/js/net/minecraft/client/entity/PlayerEntityMultiplayer.js @@ -3,11 +3,13 @@ import ClientPlayerMovementPacket from "../network/packet/play/client/ClientPlay import ClientPlayerRotationPacket from "../network/packet/play/client/ClientPlayerRotationPacket.js"; import ClientPlayerPositionPacket from "../network/packet/play/client/ClientPlayerPositionPacket.js"; import ClientPlayerPositionRotationPacket from "../network/packet/play/client/ClientPlayerPositionRotationPacket.js"; +import ClientPlayerStatePacket from "../network/packet/play/client/ClientPlayerStatePacket.js"; +import ClientSwingArmPacket from "../network/packet/play/client/ClientSwingArmPacket.js"; export default class PlayerEntityMultiplayer extends PlayerEntity { - constructor(minecraft, world, networkHandler) { - super(minecraft, world); + constructor(minecraft, world, networkHandler, id) { + super(minecraft, world, id); this.networkHandler = networkHandler; @@ -19,6 +21,9 @@ export default class PlayerEntityMultiplayer extends PlayerEntity { this.lastReportedYaw = 0; this.lastReportedPitch = 0; + + this.serverSprintState = false; + this.serverSneakState = false; } onUpdate() { @@ -26,7 +31,98 @@ export default class PlayerEntityMultiplayer extends PlayerEntity { this.onUpdateWalkingPlayer(); } + swingArm() { + super.swingArm(); + this.networkHandler.sendPacket(new ClientSwingArmPacket()); + } + + onLivingUpdate() { + this.prevCameraYaw = this.cameraYaw; + this.prevCameraPitch = this.cameraPitch; + + if (this.sprintToggleTimer > 0) { + --this.sprintToggleTimer; + } + if (this.flyToggleTimer > 0) { + --this.flyToggleTimer; + } + + let prevMoveForward = this.moveForward; + let prevJumping = this.jumping; + + this.updateKeyboardInput(); + + // Toggle jumping + if (!prevJumping && this.jumping) { + if (this.flyToggleTimer === 0) { + this.flyToggleTimer = 7; + } else { + this.flying = !this.flying; + this.flyToggleTimer = 0; + + this.updateFOVModifier(); + } + } + + // Toggle sprint + if (prevMoveForward === 0 && this.moveForward > 0) { + if (this.sprintToggleTimer === 0) { + this.sprintToggleTimer = 7; + } else { + this.sprinting = true; + this.sprintToggleTimer = 0; + + this.updateFOVModifier(); + } + } + + if (this.sprinting && (this.moveForward <= 0 || this.collision || this.isSneaking())) { + this.sprinting = false; + + this.updateFOVModifier(); + } + + super.onLivingUpdate(); + + this.jumpMovementFactor = this.speedInAir; + + if (this.sprinting) { + this.jumpMovementFactor = this.jumpMovementFactor + this.speedInAir * 0.3; + } + + let speedXZ = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); + let speedY = (Math.atan(-this.motionY * 0.2) * 15.0); + + if (speedXZ > 0.1) { + speedXZ = 0.1; + } + if (!this.onGround || this.health <= 0.0) { + speedXZ = 0.0; + } + if (this.onGround || this.health <= 0.0) { + speedY = 0.0; + } + this.cameraYaw += (speedXZ - this.cameraYaw) * 0.4; + this.cameraPitch += (speedY - this.cameraPitch) * 0.8; + } + onUpdateWalkingPlayer() { + // Send sprinting to server + let isSprinting = this.isSprinting(); + if (isSprinting !== this.serverSprintState) { + let state = isSprinting ? ClientPlayerStatePacket.START_SPRINTING : ClientPlayerStatePacket.STOP_SPRINTING; + this.networkHandler.sendPacket(new ClientPlayerStatePacket(this.id, state)); + this.serverSprintState = isSprinting; + } + + // Send sneaking to server + let isSneaking = this.isSneaking(); + if (isSneaking !== this.serverSneakState) { + let state = isSneaking ? ClientPlayerStatePacket.START_SNEAKING : ClientPlayerStatePacket.STOP_SNEAKING; + this.networkHandler.sendPacket(new ClientPlayerStatePacket(this.id, state)); + this.serverSneakState = isSneaking; + } + let movementX = this.x - this.lastReportedX; let movementY = this.y - this.lastReportedY; let movementZ = this.z - this.lastReportedZ; @@ -37,6 +133,7 @@ export default class PlayerEntityMultiplayer extends PlayerEntity { let reportPosition = movementX * movementX + movementY * movementY + movementZ * movementZ > 9.0E-4 || this.positionUpdateTicks >= 20; let reportRotation = movementYaw !== 0.0 || movementPitch !== 0.0; + // Send position and rotation to server if (reportPosition && reportRotation) { this.networkHandler.sendPacket(new ClientPlayerPositionRotationPacket(this.onGround, this.x, this.y, this.z, this.rotationYaw, this.rotationPitch)); } else if (reportPosition) { diff --git a/src/js/net/minecraft/client/network/NetworkManager.js b/src/js/net/minecraft/client/network/NetworkManager.js index b775e4d..edd5a79 100644 --- a/src/js/net/minecraft/client/network/NetworkManager.js +++ b/src/js/net/minecraft/client/network/NetworkManager.js @@ -2,6 +2,7 @@ import ByteBuf from "./util/ByteBuf.js"; import PacketRegistry from "./PacketRegistry.js"; import ProtocolState from "./ProtocolState.js"; import {require} from "../../../../Start.js"; +import MissingPackets from "../../util/MissingPackets.js"; export default class NetworkManager { @@ -204,7 +205,7 @@ export default class NetworkManager { let clazz = this.registry.getServerBoundById(this.protocolState, packetId); if (clazz === null) { if (NetworkManager.DEBUG) { - console.log("[Network] [IN] Unknown packet id: " + packetId + " (0x" + packetId.toString(16) + ")"); + console.log("[Network] [IN] Unknown packet id: " + packetId + " (0x" + packetId.toString(16) + ") (" + new MissingPackets().get(packetId) + ")"); } return; } else { diff --git a/src/js/net/minecraft/client/network/PacketRegistry.js b/src/js/net/minecraft/client/network/PacketRegistry.js index e05baef..b0ba298 100644 --- a/src/js/net/minecraft/client/network/PacketRegistry.js +++ b/src/js/net/minecraft/client/network/PacketRegistry.js @@ -24,6 +24,20 @@ import ServerDisconnectPacket from "./packet/play/server/ServerDisconnectPacket. import ServerPlayerPositionRotationPacket from "./packet/play/server/ServerPlayerPositionRotationPacket.js"; import ServerPlayerListEntryPacket from "./packet/play/server/ServerPlayerListEntryPacket.js"; import ServerPlayerListDataPacket from "./packet/play/server/ServerPlayerListDataPacket.js"; +import ServerSpawnPlayerPacket from "./packet/play/server/ServerSpawnPlayerPacket.js"; +import ServerEntityPositionRotationPacket from "./packet/play/server/ServerEntityPositionRotationPacket.js"; +import ServerEntityMovementPacket from "./packet/play/server/ServerEntityMovementPacket.js"; +import ServerEntityRotationPacket from "./packet/play/server/ServerEntityRotationPacket.js"; +import ServerEntityPositionPacket from "./packet/play/server/ServerEntityPositionPacket.js"; +import ServerEntityTeleportPacket from "./packet/play/server/ServerEntityTeleportPacket.js"; +import ServerDestroyEntitiesPacket from "./packet/play/server/ServerDestroyEntitiesPacket.js"; +import ServerEntityHeadLookPacket from "./packet/play/server/ServerEntityHeadLookPacket.js"; +import ClientPlayerStatePacket from "./packet/play/client/ClientPlayerStatePacket.js"; +import ClientSwingArmPacket from "./packet/play/client/ClientSwingArmPacket.js"; +import ServerAnimationPacket from "./packet/play/server/ServerAnimationPacket.js"; +import ServerEntityMetadataPacket from "./packet/play/server/ServerEntityMetadataPacket.js"; +import ServerConfirmTransactionPacket from "./packet/play/server/ServerConfirmTransactionPacket.js"; +import ClientConfirmTransactionPacket from "./packet/play/client/ClientConfirmTransactionPacket.js"; export default class PacketRegistry { @@ -52,9 +66,20 @@ export default class PacketRegistry { this.registerServer(ProtocolState.PLAY, 0x01, ServerJoinGamePacket); this.registerServer(ProtocolState.PLAY, 0x02, ServerChatPacket); this.registerServer(ProtocolState.PLAY, 0x08, ServerPlayerPositionRotationPacket); + this.registerServer(ProtocolState.PLAY, 0x0B, ServerAnimationPacket); + this.registerServer(ProtocolState.PLAY, 0x0C, ServerSpawnPlayerPacket); + this.registerServer(ProtocolState.PLAY, 0x13, ServerDestroyEntitiesPacket); + this.registerServer(ProtocolState.PLAY, 0x14, ServerEntityMovementPacket); + this.registerServer(ProtocolState.PLAY, 0x15, ServerEntityPositionPacket); + this.registerServer(ProtocolState.PLAY, 0x16, ServerEntityRotationPacket); + this.registerServer(ProtocolState.PLAY, 0x17, ServerEntityPositionRotationPacket); + this.registerServer(ProtocolState.PLAY, 0x18, ServerEntityTeleportPacket); + this.registerServer(ProtocolState.PLAY, 0x19, ServerEntityHeadLookPacket); + this.registerServer(ProtocolState.PLAY, 0x1C, ServerEntityMetadataPacket); this.registerServer(ProtocolState.PLAY, 0x21, ServerChunkDataPacket); this.registerServer(ProtocolState.PLAY, 0x23, ServerBlockChangePacket); this.registerServer(ProtocolState.PLAY, 0x26, ServerMultiChunkDataPacket); + this.registerServer(ProtocolState.PLAY, 0x32, ServerConfirmTransactionPacket); this.registerServer(ProtocolState.PLAY, 0x38, ServerPlayerListEntryPacket); this.registerServer(ProtocolState.PLAY, 0x40, ServerDisconnectPacket); this.registerServer(ProtocolState.PLAY, 0x47, ServerPlayerListDataPacket); @@ -65,6 +90,9 @@ export default class PacketRegistry { this.registerClient(ProtocolState.PLAY, 0x04, ClientPlayerPositionPacket); this.registerClient(ProtocolState.PLAY, 0x05, ClientPlayerRotationPacket); this.registerClient(ProtocolState.PLAY, 0x06, ClientPlayerPositionRotationPacket); + this.registerClient(ProtocolState.PLAY, 0x0A, ClientSwingArmPacket); + this.registerClient(ProtocolState.PLAY, 0x0B, ClientPlayerStatePacket); + this.registerClient(ProtocolState.PLAY, 0x0F, ClientConfirmTransactionPacket); } registerClient(state, id, packet) { diff --git a/src/js/net/minecraft/client/network/controller/PlayerController.js b/src/js/net/minecraft/client/network/controller/PlayerController.js index f36841a..6b96c61 100644 --- a/src/js/net/minecraft/client/network/controller/PlayerController.js +++ b/src/js/net/minecraft/client/network/controller/PlayerController.js @@ -7,7 +7,7 @@ export default class PlayerController { } createPlayer(world) { - return new PlayerEntity(this.minecraft, world); + return new PlayerEntity(this.minecraft, world, 0); } sendChatMessage(message) { diff --git a/src/js/net/minecraft/client/network/controller/PlayerControllerMultiplayer.js b/src/js/net/minecraft/client/network/controller/PlayerControllerMultiplayer.js index b91c8fa..df25a10 100644 --- a/src/js/net/minecraft/client/network/controller/PlayerControllerMultiplayer.js +++ b/src/js/net/minecraft/client/network/controller/PlayerControllerMultiplayer.js @@ -4,14 +4,15 @@ import ClientChatPacket from "../packet/play/client/ClientChatPacket.js"; export default class PlayerControllerMultiplayer extends PlayerController { - constructor(minecraft, networkHandler) { + constructor(minecraft, networkHandler, entityId) { super(minecraft); + this.entityId = entityId; this.networkHandler = networkHandler; } createPlayer(world) { - return new PlayerEntityMultiplayer(this.minecraft, world, this.networkHandler); + return new PlayerEntityMultiplayer(this.minecraft, world, this.networkHandler, this.entityId); } sendChatMessage(message) { diff --git a/src/js/net/minecraft/client/network/handler/NetworkPlayHandler.js b/src/js/net/minecraft/client/network/handler/NetworkPlayHandler.js index 9fe1a57..dfa4b2b 100644 --- a/src/js/net/minecraft/client/network/handler/NetworkPlayHandler.js +++ b/src/js/net/minecraft/client/network/handler/NetworkPlayHandler.js @@ -4,6 +4,9 @@ import WorldClient from "../../world/WorldClient.js"; import ClientKeepAlivePacket from "../packet/play/client/ClientKeepAlivePacket.js"; import PlayerControllerMultiplayer from "../controller/PlayerControllerMultiplayer.js"; import ClientPlayerPositionRotationPacket from "../packet/play/client/ClientPlayerPositionRotationPacket.js"; +import PlayerEntity from "../../entity/PlayerEntity.js"; +import ServerAnimationPacket from "../packet/play/server/ServerAnimationPacket.js"; +import ClientConfirmTransactionPacket from "../packet/play/client/ClientConfirmTransactionPacket.js"; export default class NetworkPlayHandler extends PacketHandler { @@ -22,7 +25,7 @@ export default class NetworkPlayHandler extends PacketHandler { } handleJoinGame(packet) { - this.minecraft.playerController = new PlayerControllerMultiplayer(this.minecraft, this); + this.minecraft.playerController = new PlayerControllerMultiplayer(this.minecraft, this, packet.entityId); let world = new WorldClient(this.minecraft); this.minecraft.loadWorld(world); } @@ -108,10 +111,110 @@ export default class NetworkPlayHandler extends PacketHandler { pitch += player.rotationPitch; } - player.setPosition(x, y, z); - player.setRotation(yaw, pitch); + player.setPositionAndRotation(x, y, z, yaw, pitch); + this.networkManager.sendPacket(new ClientPlayerPositionRotationPacket(true, player.x, player.boundingBox.minY, player.z, player.rotationYaw, player.rotationPitch)); + } - this.networkManager.sendPacket(new ClientPlayerPositionRotationPacket(player.x, player.y, player.z, player.rotationYaw, player.rotationPitch, player.onGround)); + handleServerSpawnPlayer(packet) { + let world = this.minecraft.world; + let entity = new PlayerEntity(this.minecraft, world, packet.getEntityId()); + + entity.serverPositionX = packet.getX(); + entity.serverPositionY = packet.getY(); + entity.serverPositionZ = packet.getZ(); + + let x = entity.serverPositionX / 32; + let y = entity.serverPositionY / 32; + let z = entity.serverPositionZ / 32; + + let yaw = packet.rotation ? packet.getYaw() * 360 / 256 : entity.rotationYaw; + let pitch = packet.rotation ? packet.getPitch() * 360 / 256 : entity.rotationPitch; + + entity.setPosition(x, y, z); + entity.setRotation(yaw, pitch); + + world.addEntity(entity); + } + + handleEntityMovement(packet) { + let entity = this.minecraft.world.getEntityById(packet.getEntityId()); + if (entity !== null) { + entity.serverPositionX += packet.getX(); + entity.serverPositionY += packet.getY(); + entity.serverPositionZ += packet.getZ(); + + let x = entity.serverPositionX / 32; + let y = entity.serverPositionY / 32; + let z = entity.serverPositionZ / 32; + + let yaw = packet.rotation ? packet.getYaw() * 360 / 256 : entity.rotationYaw; + let pitch = packet.rotation ? packet.getPitch() * 360 / 256 : entity.rotationPitch; + + entity.setTargetPositionAndRotation(x, y, z, yaw, pitch, 3); + + entity.onGround = packet.isOnGround(); + } + } + + handleEntityTeleport(packet) { + let entity = this.minecraft.world.getEntityById(packet.getEntityId()); + if (entity !== null) { + entity.serverPositionX = packet.getX(); + entity.serverPositionY = packet.getY(); + entity.serverPositionZ = packet.getZ(); + + let x = entity.serverPositionX / 32; + let y = entity.serverPositionY / 32; + let z = entity.serverPositionZ / 32; + + let yaw = packet.getYaw() * 360 / 256; + let pitch = packet.getPitch() * 360 / 256; + + if (Math.abs(entity.x - x) < 0.03125 && Math.abs(entity.y - y) < 0.015625 && Math.abs(entity.z - z) < 0.03125) { + entity.setTargetPositionAndRotation(entity.x, entity.y, entity.z, yaw, pitch, 3); + } else { + entity.setTargetPositionAndRotation(x, y, z, yaw, pitch, 3); + } + + entity.onGround = packet.isOnGround(); + } + } + + handleEntityMetadata(packet) { + let entity = this.minecraft.world.getEntityById(packet.getEntityId()); + if (entity !== null) { + entity.updateMetaData(packet.getMetaData()); + } + } + + handleEntityHeadLook(packet) { + let entity = this.minecraft.world.getEntityById(packet.getEntityId()); + if (entity !== null) { + entity.setRotationYawHead(packet.getHeadYaw() * 360 / 256); + } + } + + handleAnimation(packet) { + let entity = this.minecraft.world.getEntityById(packet.getEntityId()); + if (entity !== null) { + switch (packet.getAnimation()) { + case ServerAnimationPacket.SWING_ARM: + entity.swingArm(); + break; + } + } + } + + handleDestroyEntities(packet) { + for (let entityId of packet.getEntityIds()) { + this.minecraft.world.removeEntityById(entityId); + } + } + + handleConfirmTransaction(packet) { + if (!packet.isAccepted()) { + this.networkManager.sendPacket(new ClientConfirmTransactionPacket(packet.getWindowId(), packet.getActionId(), true)); + } } handleChunkData(packet) { diff --git a/src/js/net/minecraft/client/network/packet/play/client/ClientConfirmTransactionPacket.js b/src/js/net/minecraft/client/network/packet/play/client/ClientConfirmTransactionPacket.js new file mode 100644 index 0000000..d8c961a --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/client/ClientConfirmTransactionPacket.js @@ -0,0 +1,18 @@ +import Packet from "../../../Packet.js"; + +export default class ClientConfirmTransactionPacket extends Packet { + + constructor(windowId, actionId, accepted) { + super(); + + this.windowId = windowId; + this.actionId = actionId; + this.accepted = accepted; + } + + write(buffer) { + buffer.writeByte(this.windowId); + buffer.writeShort(this.actionId); + buffer.writeByte(this.accepted ? 1 : 0); + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/client/ClientPlayerStatePacket.js b/src/js/net/minecraft/client/network/packet/play/client/ClientPlayerStatePacket.js new file mode 100644 index 0000000..f587e46 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/client/ClientPlayerStatePacket.js @@ -0,0 +1,26 @@ +import Packet from "../../../Packet.js"; + +export default class ClientPlayerStatePacket extends Packet { + + static START_SNEAKING = 0; + static STOP_SNEAKING = 1; + static STOP_SLEEPING = 2; + static START_SPRINTING = 3; + static STOP_SPRINTING = 4; + static RIDING_JUMP = 5; + static OPEN_INVENTORY = 6; + + constructor(entityId, state, jumpBoost = 0) { + super(); + + this.entityId = entityId; + this.state = state; + this.jumpBoost = jumpBoost; + } + + write(buffer) { + buffer.writeVarInt(this.entityId); + buffer.writeByte(this.state); + buffer.writeVarInt(this.jumpBoost); + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/client/ClientSwingArmPacket.js b/src/js/net/minecraft/client/network/packet/play/client/ClientSwingArmPacket.js new file mode 100644 index 0000000..a88395a --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/client/ClientSwingArmPacket.js @@ -0,0 +1,8 @@ +import Packet from "../../../Packet.js"; + +export default class ClientSwingArmPacket extends Packet { + + constructor() { + super(); + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerAnimationPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerAnimationPacket.js new file mode 100644 index 0000000..7e4f3fc --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerAnimationPacket.js @@ -0,0 +1,35 @@ +import Packet from "../../../Packet.js"; + +export default class ServerAnimationPacket extends Packet { + + static SWING_ARM = 0; + static DAMAGE = 1; + static LEAVE_BED = 2; + static EAT_FOOD = 3; + static CRITICAL_HIT = 4; + static ENCHANTMENT_CRITICAL_HIT = 5; + + constructor() { + super(); + + this.entityId = 0; + this.animation = 0; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + this.animation = buffer.readByte(); + } + + handle(handler) { + handler.handleAnimation(this); + } + + getEntityId() { + return this.entityId; + } + + getAnimation() { + return this.animation; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerConfirmTransactionPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerConfirmTransactionPacket.js new file mode 100644 index 0000000..8d42f5c --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerConfirmTransactionPacket.js @@ -0,0 +1,34 @@ +import Packet from "../../../Packet.js"; + +export default class ServerConfirmTransactionPacket extends Packet { + + constructor() { + super(); + + this.windowId = 0; + this.actionId = 0; + this.accepted = false; + } + + read(buffer) { + this.windowId = buffer.readByte(); + this.actionId = buffer.readShort(); + this.accepted = buffer.readBoolean(); + } + + handle(handler) { + handler.handleConfirmTransaction(this); + } + + getWindowId() { + return this.windowId; + } + + getActionId() { + return this.actionId; + } + + isAccepted() { + return this.accepted; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerDestroyEntitiesPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerDestroyEntitiesPacket.js new file mode 100644 index 0000000..96ac0e0 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerDestroyEntitiesPacket.js @@ -0,0 +1,25 @@ +import Packet from "../../../Packet.js"; + +export default class ServerDestroyEntitiesPacket extends Packet { + + constructor() { + super(); + + this.entityIds = []; + } + + read(buffer) { + let amount = buffer.readVarInt(); + for (let i = 0; i < amount; i++) { + this.entityIds.push(buffer.readVarInt()); + } + } + + handle(handler) { + handler.handleDestroyEntities(this); + } + + getEntityIds() { + return this.entityIds; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityHeadLookPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityHeadLookPacket.js new file mode 100644 index 0000000..452b942 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityHeadLookPacket.js @@ -0,0 +1,28 @@ +import Packet from "../../../Packet.js"; + +export default class ServerEntityHeadLookPacket extends Packet { + + constructor() { + super(); + + this.entityId = 0; + this.headYaw = 0; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + this.headYaw = buffer.readByte(); + } + + handle(handler) { + handler.handleEntityHeadLook(this); + } + + getEntityId() { + return this.entityId; + } + + getHeadYaw() { + return this.headYaw; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMetadataPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMetadataPacket.js new file mode 100644 index 0000000..1e987a5 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMetadataPacket.js @@ -0,0 +1,28 @@ +import Packet from "../../../Packet.js"; + +export default class ServerEntityMetadataPacket extends Packet { + + constructor() { + super(); + + this.entityId = 0; + this.metaData = null; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + this.metaData = buffer.readMetaData(); + } + + handle(handler) { + handler.handleEntityMetadata(this); + } + + getEntityId() { + return this.entityId; + } + + getMetaData() { + return this.metaData; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMovementPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMovementPacket.js new file mode 100644 index 0000000..f245806 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityMovementPacket.js @@ -0,0 +1,71 @@ +import Packet from "../../../Packet.js"; + +export default class ServerEntityMovementPacket extends Packet { + + constructor() { + super(); + + this.position = false; + this.rotation = false; + + this.entityId = 0; + + this.onGround = false; + + this.x = 0; + this.y = 0; + this.z = 0; + + this.yaw = 0; + this.pitch = 0; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + + if (this.position) { + this.x = buffer.readByte(); + this.y = buffer.readByte(); + this.z = buffer.readByte(); + } + + if (this.rotation) { + this.yaw = buffer.readByte(); + this.pitch = buffer.readByte(); + } + + this.onGround = buffer.readBoolean(); + } + + handle(packetHandler) { + packetHandler.handleEntityMovement(this); + } + + getEntityId() { + return this.entityId; + } + + getX() { + return this.x; + } + + getY() { + return this.y; + } + + getZ() { + return this.z; + } + + getYaw() { + return this.yaw; + } + + getPitch() { + return this.pitch; + } + + isOnGround() { + return this.onGround; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionPacket.js new file mode 100644 index 0000000..27b0b61 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionPacket.js @@ -0,0 +1,10 @@ +import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js"; + +export default class ServerEntityPositionPacket extends ServerEntityMovementPacket { + + constructor() { + super(); + + this.position = true; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionRotationPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionRotationPacket.js new file mode 100644 index 0000000..46309bb --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityPositionRotationPacket.js @@ -0,0 +1,11 @@ +import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js"; + +export default class ServerEntityPositionRotationPacket extends ServerEntityMovementPacket { + + constructor() { + super(); + + this.position = true; + this.position = true; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityRotationPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityRotationPacket.js new file mode 100644 index 0000000..65ba0a4 --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityRotationPacket.js @@ -0,0 +1,10 @@ +import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js"; + +export default class ServerEntityRotationPacket extends ServerEntityMovementPacket { + + constructor() { + super(); + + this.rotation = true; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerEntityTeleportPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityTeleportPacket.js new file mode 100644 index 0000000..f2bdd4e --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerEntityTeleportPacket.js @@ -0,0 +1,61 @@ +import Packet from "../../../Packet.js"; + +export default class ServerEntityTeleportPacket extends Packet { + + constructor() { + super(); + + this.entityId = 0; + + this.x = 0; + this.y = 0; + this.z = 0; + + this.yaw = 0; + this.pitch = 0; + + this.onGround = false; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + this.x = buffer.readInt(); + this.y = buffer.readInt(); + this.z = buffer.readInt(); + this.yaw = buffer.readByte(); + this.pitch = buffer.readByte(); + this.onGround = buffer.readBoolean(); + } + + handle(packetHandler) { + packetHandler.handleEntityTeleport(this); + } + + getEntityId() { + return this.entityId; + } + + getX() { + return this.x; + } + + getY() { + return this.y; + } + + getZ() { + return this.z; + } + + getYaw() { + return this.yaw; + } + + getPitch() { + return this.pitch; + } + + isOnGround() { + return this.onGround; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/packet/play/server/ServerSpawnPlayerPacket.js b/src/js/net/minecraft/client/network/packet/play/server/ServerSpawnPlayerPacket.js new file mode 100644 index 0000000..a19607e --- /dev/null +++ b/src/js/net/minecraft/client/network/packet/play/server/ServerSpawnPlayerPacket.js @@ -0,0 +1,75 @@ +import Packet from "../../../Packet.js"; + +export default class ServerSpawnPlayerPacket extends Packet { + + constructor() { + super(); + + this.entityId = 0; + this.uuid = null; + + this.x = 0; + this.y = 0; + this.z = 0; + + this.yaw = 0; + this.pitch = 0; + + this.currentItem = 0; + } + + read(buffer) { + this.entityId = buffer.readVarInt(); + this.uuid = buffer.readUUID(); + + this.x = buffer.readInt(); + this.y = buffer.readInt(); + this.z = buffer.readInt(); + + this.yaw = buffer.readByte(); + this.pitch = buffer.readByte(); + + this.currentItem = buffer.readShort(); + this.metaData = buffer.readMetaData(); + } + + handle(handler) { + handler.handleServerSpawnPlayer(this); + } + + getEntityId() { + return this.entityId; + } + + getUUID() { + return this.uuid; + } + + getX() { + return this.x; + } + + getY() { + return this.y; + } + + getZ() { + return this.z; + } + + getYaw() { + return this.yaw; + } + + getPitch() { + return this.pitch; + } + + getMetaData() { + return this.metaData; + } + + getCurrentItem() { + return this.currentItem; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/network/util/ByteBuf.js b/src/js/net/minecraft/client/network/util/ByteBuf.js index 6f1492a..448cddd 100644 --- a/src/js/net/minecraft/client/network/util/ByteBuf.js +++ b/src/js/net/minecraft/client/network/util/ByteBuf.js @@ -2,6 +2,8 @@ import Long from "../../../../../../../libraries/long.js"; import BlockPosition from "../../../util/BlockPosition.js"; import UUID from "../../../util/UUID.js"; import {format} from "../../../../../../../libraries/chat.js"; +import Vector3 from "../../../util/Vector3.js"; +import NBTIO from "../../../nbt/NBTIO.js"; export default class ByteBuf { @@ -228,6 +230,79 @@ export default class ByteBuf { return format(JSON.parse(this.readString(32767))); } + readMetaData() { + let metaData = {}; + + let data = 0; + while ((data = this.readByte()) !== 0x7f) { + let typeId = (data & 0xE0) >> 5; + let id = data & 0x1F; + + let value = null; + switch (typeId) { + case 0: + value = this.readByte(); + break; + case 1: + value = this.readShort(); + break; + case 2: + value = this.readInt(); + break; + case 3: + value = this.readFloat(); + break; + case 4: + value = this.readString(); + break; + case 5: + value = this.readItem(); + break; + case 6: + value = new BlockPosition(this.readInt(), this.readInt(), this.readInt()); + break; + case 7: + value = new Vector3(this.readFloat(), this.readFloat(), this.readFloat()); + break; + default: + throw new Error("Unknown meta data type: " + typeId); + } + metaData[id] = { + id: id, + type: typeId, + value: value + }; + } + + return metaData; + } + + readItem() { + let item = this.readShort(); + if (item < 0) { + return null; + } else { + let a = this.readByte(); + let b = this.readShort(); + let c = this.readNBT(); + + // TODO create item + return item; + } + } + + readNBT() { + let position = this.getPosition(); + + let tagId = this.readByte(); + if (tagId === 0) { + return null; + } else { + this.setPosition(position); + return NBTIO.readTag(this); // TODO + } + } + readableBytes() { return this.array.length - this.pos; } diff --git a/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js b/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js index da9058a..cea0cb4 100644 --- a/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js +++ b/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js @@ -25,8 +25,9 @@ export default class PlayerRenderer extends EntityRenderer { let firstPerson = this.worldRenderer.minecraft.settings.thirdPersonView === 0; let itemId = firstPerson ? this.worldRenderer.itemToRender : entity.inventory.getItemInSelectedSlot(); let hasItem = itemId !== 0; + let isSelf = entity === this.worldRenderer.minecraft.player; - if (firstPerson && hasItem) { + if (firstPerson && hasItem && isSelf) { super.rebuild(entity); // Create new item group and add it to the hand @@ -72,7 +73,12 @@ export default class PlayerRenderer extends EntityRenderer { } this.model.swingProgress = entity.prevSwingProgress + swingProgress * partialTicks; this.model.hasItemInHand = entity.inventory.getItemInSelectedSlot() !== 0; - this.model.isSneaking = entity.sneaking; + this.model.isSneaking = entity.isSneaking(); + + // TODO find a better way + if (entity !== this.worldRenderer.minecraft.player) { + this.firstPersonGroup.visible = false; + } super.render(entity, partialTicks); } diff --git a/src/js/net/minecraft/client/world/Chunk.js b/src/js/net/minecraft/client/world/Chunk.js index 701e08f..1e7a732 100644 --- a/src/js/net/minecraft/client/world/Chunk.js +++ b/src/js/net/minecraft/client/world/Chunk.js @@ -195,7 +195,7 @@ export default class Chunk { while (y > 0) { let typeId = this.getBlockAt(x, y - 1, z); let block = Block.getById(typeId); - let opacity = typeId === 0 ? 0 : block.getOpacity(); + let opacity = typeId === 0 || block === null ? 0 : block.getOpacity(); if (opacity !== 0) { break; diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index 481b45c..8b22ed6 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -43,6 +43,11 @@ export default class World { } onTick() { + // Tick entities + for (let i = 0; i < this.entities.length; i++) { + this.entities[i].onUpdate(); + } + // Update skylight subtracted (To make the night dark) let lightLevel = this.calculateSkylightSubtracted(1.0); if (lightLevel !== this.skylightSubtracted) { @@ -566,8 +571,10 @@ export default class World { removeEntityById(id) { let entity = this.getEntityById(id); - this.entities.remove(entity); - this.group.remove(entity.renderer.group); + if (entity !== null) { + this.entities.splice(this.entities.indexOf(entity), 1); + this.group.remove(entity.renderer.group); + } } getEntityById(id) { @@ -602,4 +609,10 @@ export default class World { return this.chunkProvider; } + clearEntities() { + for (let entity of this.entities) { + this.removeEntityById(entity.id); + } + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/NBTIO.js b/src/js/net/minecraft/nbt/NBTIO.js new file mode 100644 index 0000000..e37e919 --- /dev/null +++ b/src/js/net/minecraft/nbt/NBTIO.js @@ -0,0 +1,29 @@ +import TagRegistry from "./tag/TagRegistry.js"; + +export default class { + + static readTag(buffer) { + let id = buffer.readUnsignedByte(); + if (id === 0) { + return null; + } + + let nameLength = buffer.readShort(); + let nameBytes = new Uint8Array(nameLength); + buffer.read(nameBytes, nameLength); + let name = new TextDecoder().decode(nameBytes); + + let tag = TagRegistry.createInstance(id, name); + tag.read(buffer); + return tag; + } + + static writeTag(buffer, tag) { + let nameBytes = new TextEncoder().encode(tag.getName()); + buffer.writeByte(TagRegistry.getIdFor(tag)); + buffer.writeShort(nameBytes.length); + buffer.write(nameBytes); + tag.write(buffer); + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/TagRegistry.js b/src/js/net/minecraft/nbt/tag/TagRegistry.js new file mode 100644 index 0000000..3c508a5 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/TagRegistry.js @@ -0,0 +1,61 @@ +import ByteTag from "./builtin/ByteTag.js"; +import CompoundTag from "./builtin/CompoundTag.js"; +import ShortTag from "./builtin/ShortTag.js"; +import IntTag from "./builtin/IntTag.js"; +import LongTag from "./builtin/LongTag.js"; +import FloatTag from "./builtin/FloatTag.js"; +import DoubleTag from "./builtin/DoubleTag.js"; +import StringTag from "./builtin/StringTag.js"; +import ByteArrayTag from "./builtin/ByteArrayTag.js"; +import ListTag from "./builtin/ListTag.js"; +import IntArrayTag from "./builtin/IntArrayTag.js"; + +export default class TagRegistry { + + static idToTag = new Map(); + static tagToId = new Map(); + + static { + TagRegistry.register(1, ByteTag); + TagRegistry.register(2, ShortTag); + TagRegistry.register(3, IntTag); + TagRegistry.register(4, LongTag); + TagRegistry.register(5, FloatTag); + TagRegistry.register(6, DoubleTag); + TagRegistry.register(7, ByteArrayTag); + TagRegistry.register(8, StringTag); + TagRegistry.register(9, ListTag); + TagRegistry.register(10, CompoundTag); + TagRegistry.register(11, IntArrayTag); + } + + static register(id, tag) { + TagRegistry.idToTag.set(id, tag); + TagRegistry.tagToId.set(tag, id); + } + + static getIdFor(clazz) { + let id = TagRegistry.tagToId.get(clazz); + if (typeof id === "undefined") { + return -1; + } + return id; + } + + static getClassFor(id) { + let clazz = TagRegistry.idToTag.get(id); + if (typeof clazz === "undefined") { + return null; + } + return clazz; + } + + static createInstance(id, tagName) { + let clazz = TagRegistry.idToTag.get(id); + if (clazz === null || typeof clazz === "undefined") { + return null; + } + return new clazz(tagName); + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/ByteArrayTag.js b/src/js/net/minecraft/nbt/tag/builtin/ByteArrayTag.js new file mode 100644 index 0000000..1e439a9 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/ByteArrayTag.js @@ -0,0 +1,28 @@ +import Tag from "./Tag.js"; + +export default class ByteArrayTag extends Tag { + + constructor(name, value = new Uint8Array(0)) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeInt(this.value.length); + buffer.write(this.value, this.value.length); + } + + read(buffer) { + this.value = new Uint8Array(buffer.readInt()); + buffer.read(this.value, this.value.length); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/ByteTag.js b/src/js/net/minecraft/nbt/tag/builtin/ByteTag.js new file mode 100644 index 0000000..2e3c3f9 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/ByteTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class ByteTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeByte(this.value); + } + + read(buffer) { + this.value = buffer.readByte(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/CompoundTag.js b/src/js/net/minecraft/nbt/tag/builtin/CompoundTag.js new file mode 100644 index 0000000..3185454 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/CompoundTag.js @@ -0,0 +1,41 @@ +import Tag from "./Tag.js"; +import NBTIO from "../../NBTIO.js"; + +export default class CompoundTag extends Tag { + + constructor(name, value = new Map()) { + super(name); + + this.value = value; + } + + write(buffer) { + for (let [key, tag] of this.value) { + NBTIO.writeTag(buffer, tag); + } + buffer.writeByte(0); + } + + read(buffer) { + let tags = []; + let tag = null; + while ((tag = NBTIO.readTag(buffer)) !== null) { + tags.push(tag); + } + for (let tag of tags) { + this.put(tag); + } + } + + put(tag) { + this.value.set(tag.getName(), tag); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/DoubleTag.js b/src/js/net/minecraft/nbt/tag/builtin/DoubleTag.js new file mode 100644 index 0000000..e268332 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/DoubleTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class DoubleTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeDouble(this.value); + } + + read(buffer) { + this.value = buffer.readDouble(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/FloatTag.js b/src/js/net/minecraft/nbt/tag/builtin/FloatTag.js new file mode 100644 index 0000000..32ec723 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/FloatTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class FloatTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeFloat(this.value); + } + + read(buffer) { + this.value = buffer.readFloat(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/IntArrayTag.js b/src/js/net/minecraft/nbt/tag/builtin/IntArrayTag.js new file mode 100644 index 0000000..2bfdabc --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/IntArrayTag.js @@ -0,0 +1,32 @@ +import Tag from "./Tag.js"; + +export default class IntArrayTag extends Tag { + + constructor(name, value = []) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeInt(this.value.length); + for (let i = 0; i < this.value.length; i++) { + buffer.writeInt(this.value[i]); + } + } + + read(buffer) { + this.value = new Uint8Array(buffer.readInt()); + for (let i = 0; i < this.value.length; i++) { + this.value[i] = buffer.readInt(); + } + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/IntTag.js b/src/js/net/minecraft/nbt/tag/builtin/IntTag.js new file mode 100644 index 0000000..f72bc17 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/IntTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class IntTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeInt(this.value); + } + + read(buffer) { + this.value = buffer.readInt(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/ListTag.js b/src/js/net/minecraft/nbt/tag/builtin/ListTag.js new file mode 100644 index 0000000..705e293 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/ListTag.js @@ -0,0 +1,54 @@ +import Tag from "./Tag.js"; +import TagRegistry from "../TagRegistry.js"; + +export default class ListTag extends Tag { + + constructor(name, type, value = []) { + super(name); + + this.type = type; + this.value = value; + } + + write(buffer) { + if (this.value.length === 0) { + buffer.writeByte(0); + } else { + let id = TagRegistry.getIdFor(this.type); + if (id === -1) { + throw new Error("Unknown tag type: " + this.type); + } + buffer.writeByte(id); + } + + buffer.writeInt(this.value.length); + for (let i = 0; i < this.value.length; i++) { + this.value[i].write(buffer); + } + } + + read(buffer) { + let id = buffer.readByte(); + this.type = TagRegistry.getClassFor(id); + this.value = []; + + let length = buffer.readInt(); + for (let i = 0; i < length; i++) { + let tag = TagRegistry.createInstance(id, ""); + tag.read(buffer); + this.add(tag); + } + } + + add(tag) { + this.value.push(tag); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/LongTag.js b/src/js/net/minecraft/nbt/tag/builtin/LongTag.js new file mode 100644 index 0000000..c451ead --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/LongTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class LongTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeLong(this.value); + } + + read(buffer) { + this.value = buffer.readLong(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/ShortTag.js b/src/js/net/minecraft/nbt/tag/builtin/ShortTag.js new file mode 100644 index 0000000..559d9b6 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/ShortTag.js @@ -0,0 +1,26 @@ +import Tag from "./Tag.js"; + +export default class ShortTag extends Tag { + + constructor(name, value = 0) { + super(name); + + this.value = value; + } + + write(buffer) { + buffer.writeShort(this.value); + } + + read(buffer) { + this.value = buffer.readShort(); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/StringTag.js b/src/js/net/minecraft/nbt/tag/builtin/StringTag.js new file mode 100644 index 0000000..18ee91c --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/StringTag.js @@ -0,0 +1,31 @@ +import Tag from "./Tag.js"; + +export default class StringTag extends Tag { + + constructor(name, value = "") { + super(name); + + this.value = value; + } + + write(buffer) { + let bytes = new TextEncoder().encode(this.value); + buffer.writeShort(bytes.length); + buffer.write(bytes, bytes.length); + } + + read(buffer) { + let length = buffer.readShort(); + let bytes = new Uint8Array(length); + buffer.read(bytes, length); + this.value = new TextDecoder().decode(bytes); + } + + getValue() { + return this.value; + } + + setValue(value) { + this.value = value; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/nbt/tag/builtin/Tag.js b/src/js/net/minecraft/nbt/tag/builtin/Tag.js new file mode 100644 index 0000000..1d541f4 --- /dev/null +++ b/src/js/net/minecraft/nbt/tag/builtin/Tag.js @@ -0,0 +1,17 @@ +export default class Tag { + constructor(name) { + this.name = name; + } + + getName() { + return this.name; + } + + write(buffer) { + + } + + read(buffer) { + + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/util/MissingPackets.js b/src/js/net/minecraft/util/MissingPackets.js new file mode 100644 index 0000000..2d87c04 --- /dev/null +++ b/src/js/net/minecraft/util/MissingPackets.js @@ -0,0 +1,91 @@ +export default class MissingPackets { + + constructor() { + this.table = {}; + + this.map(0, "ServerKeepAlivePacket"); + this.map(1, "ServerJoinGamePacket"); + this.map(2, "ServerChatPacket"); + this.map(3, "ServerUpdateTimePacket"); + this.map(4, "ServerEntityEquipmentPacket"); + this.map(5, "ServerSpawnPositionPacket"); + this.map(6, "ServerUpdateHealthPacket"); + this.map(7, "ServerRespawnPacket"); + this.map(8, "ServerPlayerPositionRotationPacket"); + this.map(9, "ServerChangeHeldItemPacket"); + this.map(10, "ServerPlayerUseBedPacket"); + this.map(11, "ServerAnimationPacket"); + this.map(12, "ServerSpawnPlayerPacket"); + this.map(13, "ServerCollectItemPacket"); + this.map(14, "ServerSpawnObjectPacket"); + this.map(15, "ServerSpawnMobPacket"); + this.map(16, "ServerSpawnPaintingPacket"); + this.map(17, "ServerSpawnExpOrbPacket"); + this.map(18, "ServerEntityVelocityPacket"); + this.map(19, "ServerDestroyEntitiesPacket"); + this.map(20, "ServerEntityMovementPacket"); + this.map(21, "ServerEntityPositionPacket"); + this.map(22, "ServerEntityRotationPacket"); + this.map(23, "ServerEntityPositionRotationPacket"); + this.map(24, "ServerEntityTeleportPacket"); + this.map(25, "ServerEntityHeadLookPacket"); + this.map(26, "ServerEntityStatusPacket"); + this.map(27, "ServerEntityAttachPacket"); + this.map(28, "ServerEntityMetadataPacket"); + this.map(29, "ServerEntityEffectPacket"); + this.map(30, "ServerEntityRemoveEffectPacket"); + this.map(31, "ServerSetExperiencePacket"); + this.map(32, "ServerEntityPropertiesPacket"); + this.map(33, "ServerChunkDataPacket"); + this.map(34, "ServerMultiBlockChangePacket"); + this.map(35, "ServerBlockChangePacket"); + this.map(36, "ServerBlockValuePacket"); + this.map(37, "ServerBlockBreakAnimPacket"); + this.map(38, "ServerMultiChunkDataPacket"); + this.map(39, "ServerExplosionPacket"); + this.map(40, "ServerPlayEffectPacket"); + this.map(41, "ServerPlaySoundPacket"); + this.map(42, "ServerSpawnParticlePacket"); + this.map(43, "ServerNotifyClientPacket"); + this.map(44, "ServerSpawnGlobalEntityPacket"); + this.map(45, "ServerOpenWindowPacket"); + this.map(46, "ServerCloseWindowPacket"); + this.map(47, "ServerSetSlotPacket"); + this.map(48, "ServerWindowItemsPacket"); + this.map(49, "ServerWindowPropertyPacket"); + this.map(50, "ServerConfirmTransactionPacket"); + this.map(51, "ServerUpdateSignPacket"); + this.map(52, "ServerMapDataPacket"); + this.map(53, "ServerUpdateTileEntityPacket"); + this.map(54, "ServerOpenTileEntityEditorPacket"); + this.map(55, "ServerStatisticsPacket"); + this.map(56, "ServerPlayerListEntryPacket"); + this.map(57, "ServerPlayerAbilitiesPacket"); + this.map(58, "ServerTabCompletePacket"); + this.map(59, "ServerScoreboardObjectivePacket"); + this.map(60, "ServerUpdateScorePacket"); + this.map(61, "ServerDisplayScoreboardPacket"); + this.map(62, "ServerTeamPacket"); + this.map(63, "ServerPluginMessagePacket"); + this.map(64, "ServerDisconnectPacket"); + this.map(65, "ServerDifficultyPacket"); + this.map(66, "ServerCombatPacket"); + this.map(67, "ServerSwitchCameraPacket"); + this.map(68, "ServerWorldBorderPacket"); + this.map(69, "ServerTitlePacket"); + this.map(70, "ServerSetCompressionPacket"); + this.map(71, "ServerPlayerListDataPacket"); + this.map(72, "ServerResourcePackSendPacket"); + this.map(73, "ServerEntityNBTUpdatePacket"); + } + + map(id, name) { + this.table[id] = name; + } + + get(id) { + return this.table[id]; + } + + +} \ No newline at end of file