implement player spawning, movement, animation, metadata and destroying, implement NBT serialization, version 1.1.7

This commit is contained in:
LabyStudio
2022-06-20 03:16:20 +02:00
parent 4ac61adbb5
commit 19a131bd94
44 changed files with 1481 additions and 138 deletions
+10 -4
View File
@@ -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();
}
+67 -13
View File
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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) {
@@ -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 {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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);
}
}
@@ -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);
}
}
@@ -0,0 +1,8 @@
import Packet from "../../../Packet.js";
export default class ClientSwingArmPacket extends Packet {
constructor() {
super();
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -0,0 +1,10 @@
import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js";
export default class ServerEntityPositionPacket extends ServerEntityMovementPacket {
constructor() {
super();
this.position = true;
}
}
@@ -0,0 +1,11 @@
import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js";
export default class ServerEntityPositionRotationPacket extends ServerEntityMovementPacket {
constructor() {
super();
this.position = true;
this.position = true;
}
}
@@ -0,0 +1,10 @@
import ServerEntityMovementPacket from "./ServerEntityMovementPacket.js";
export default class ServerEntityRotationPacket extends ServerEntityMovementPacket {
constructor() {
super();
this.rotation = true;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
@@ -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);
}
+1 -1
View File
@@ -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;
+15 -2
View File
@@ -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);
}
}
}