373 lines
11 KiB
JavaScript
373 lines
11 KiB
JavaScript
import EntityLiving from "./EntityLiving.js";
|
|
import Block from "../world/block/Block.js";
|
|
import MathHelper from "../../util/MathHelper.js";
|
|
import Keyboard from "../../util/Keyboard.js";
|
|
import Vector3 from "../../util/Vector3.js";
|
|
import {BlockRegistry} from "../world/block/BlockRegistry.js";
|
|
import InventoryPlayer from "../inventory/inventory/InventoryPlayer.js";
|
|
|
|
export default class PlayerEntity extends EntityLiving {
|
|
|
|
static name = "PlayerEntity";
|
|
|
|
constructor(minecraft, world, id) {
|
|
super(minecraft, world, id);
|
|
|
|
this.inventory = new InventoryPlayer();
|
|
this.username = "Player";
|
|
|
|
this.collision = false;
|
|
|
|
this.jumpMovementFactor = 0.02;
|
|
this.speedInAir = 0.02;
|
|
this.flySpeed = 0.05;
|
|
this.stepHeight = 0.5;
|
|
|
|
this.flyToggleTimer = 0;
|
|
this.sprintToggleTimer = 0;
|
|
|
|
this.sprinting = false;
|
|
this.flying = false;
|
|
|
|
this.prevFovModifier = 0;
|
|
this.fovModifier = 0;
|
|
this.timeFovChanged = 0;
|
|
|
|
this.renderArmPitch = 0;
|
|
this.renderArmYaw = 0;
|
|
|
|
this.prevRenderArmPitch = 0;
|
|
this.prevRenderArmYaw = 0;
|
|
|
|
// For first person bobbing
|
|
this.cameraYaw = 0;
|
|
this.cameraPitch = 0;
|
|
this.prevCameraYaw = 0;
|
|
this.prevCameraPitch = 0;
|
|
|
|
this.width = 0.6;
|
|
this.height = 1.8;
|
|
}
|
|
|
|
respawn() {
|
|
let spawn = this.world.getSpawn();
|
|
this.setPosition(spawn.x, spawn.y, spawn.z);
|
|
}
|
|
|
|
turn(motionX, motionY) {
|
|
let sensitivity = this.minecraft.settings.sensitivity / 500;
|
|
this.rotationYaw = this.rotationYaw + motionX * sensitivity;
|
|
this.rotationPitch = this.rotationPitch - motionY * sensitivity;
|
|
|
|
if (this.rotationPitch < -90.0) {
|
|
this.rotationPitch = -90.0;
|
|
}
|
|
|
|
if (this.rotationPitch > 90.0) {
|
|
this.rotationPitch = 90.0;
|
|
}
|
|
}
|
|
|
|
onUpdate() {
|
|
super.onUpdate();
|
|
}
|
|
|
|
onLivingUpdate() {
|
|
super.onLivingUpdate();
|
|
}
|
|
|
|
isInWater() {
|
|
return this.world.getBlockAt(this.getBlockPosX(), this.getBlockPosY(), this.getBlockPosZ()) === BlockRegistry.WATER.getId();
|
|
}
|
|
|
|
isHeadInWater() {
|
|
let cameraPosition = this.world.minecraft.worldRenderer.camera.position;
|
|
return this.world.getBlockAt(
|
|
Math.floor(cameraPosition.x),
|
|
Math.floor(cameraPosition.y + 0.12),
|
|
Math.floor(cameraPosition.z)
|
|
) === BlockRegistry.WATER.getId()
|
|
}
|
|
|
|
jump() {
|
|
this.motionY = 0.42;
|
|
|
|
if (this.sprinting) {
|
|
let radiansYaw = MathHelper.toRadians(this.rotationYaw + 180);
|
|
this.motionX -= Math.sin(radiansYaw) * 0.2;
|
|
this.motionZ += Math.cos(radiansYaw) * 0.2;
|
|
}
|
|
}
|
|
|
|
travelFlying(forward, vertical, strafe) {
|
|
// Fly move up and down
|
|
if (this.isSneaking()) {
|
|
this.moveStrafing = strafe / 0.3;
|
|
this.moveForward = forward / 0.3;
|
|
this.motionY -= this.flySpeed * 3.0;
|
|
}
|
|
|
|
if (this.jumping) {
|
|
this.motionY += this.flySpeed * 3.0;
|
|
}
|
|
|
|
let prevMotionY = this.motionY;
|
|
let prevJumpMovementFactor = this.jumpMovementFactor;
|
|
this.jumpMovementFactor = this.flySpeed * (this.sprinting ? 2 : 1);
|
|
|
|
this.travel(forward, vertical, strafe);
|
|
|
|
this.motionY = prevMotionY * 0.6;
|
|
this.jumpMovementFactor = prevJumpMovementFactor;
|
|
|
|
if (this.onGround) {
|
|
this.flying = false;
|
|
}
|
|
}
|
|
|
|
travelInWater(forward, vertical, strafe) {
|
|
let slipperiness = 0.8;
|
|
let friction = 0.02;
|
|
|
|
this.moveRelative(forward, vertical, strafe, friction);
|
|
this.collision = this.moveCollide(-this.motionX, this.motionY, -this.motionZ);
|
|
|
|
this.motionX *= slipperiness;
|
|
this.motionY *= 0.8;
|
|
this.motionZ *= slipperiness;
|
|
this.motionY -= 0.02;
|
|
}
|
|
|
|
travel(forward, vertical, strafe) {
|
|
let isSlow = this.onGround && this.isSneaking();
|
|
|
|
let prevX = this.x;
|
|
let prevZ = this.z;
|
|
|
|
if (this === this.world.minecraft.player) {
|
|
let prevSlipperiness = this.getBlockSlipperiness() * 0.91;
|
|
|
|
let value = 0.16277136 / (prevSlipperiness * prevSlipperiness * prevSlipperiness);
|
|
let friction;
|
|
|
|
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;
|
|
}
|
|
|
|
// Step sound
|
|
if (!isSlow) {
|
|
let blockX = MathHelper.floor(this.x);
|
|
let blockY = MathHelper.floor(this.y - 0.2);
|
|
let blockZ = MathHelper.floor(this.z);
|
|
let typeId = this.world.getBlockAt(blockX, blockY, blockZ);
|
|
|
|
let distanceX = this.x - prevX;
|
|
let distanceZ = this.z - prevZ;
|
|
|
|
this.distanceWalked += Math.sqrt(distanceX * distanceX + distanceZ * distanceZ) * 0.6;
|
|
if (this.distanceWalked > this.nextStepDistance && typeId !== 0) {
|
|
this.nextStepDistance = this.distanceWalked + 1;
|
|
|
|
let block = Block.getById(typeId);
|
|
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());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
getBlockSlipperiness() {
|
|
return this.onGround ? 0.6 : 1.0;
|
|
}
|
|
|
|
getAIMoveSpeed() {
|
|
return this.sprinting ? 0.13 : 0.1;
|
|
}
|
|
|
|
moveRelative(forward, up, strafe, friction) {
|
|
let distance = strafe * strafe + up * up + forward * forward;
|
|
|
|
if (distance >= 0.0001) {
|
|
distance = Math.sqrt(distance);
|
|
|
|
if (distance < 1.0) {
|
|
distance = 1.0;
|
|
}
|
|
|
|
distance = friction / distance;
|
|
strafe = strafe * distance;
|
|
up = up * distance;
|
|
forward = forward * distance;
|
|
|
|
let yawRadians = MathHelper.toRadians(this.rotationYaw + 180);
|
|
let sin = Math.sin(yawRadians);
|
|
let cos = Math.cos(yawRadians);
|
|
|
|
this.motionX += strafe * cos - forward * sin;
|
|
this.motionY += up;
|
|
this.motionZ += forward * cos + strafe * sin;
|
|
}
|
|
}
|
|
|
|
updateKeyboardInput() {
|
|
let moveForward = 0.0;
|
|
let moveStrafe = 0.0;
|
|
|
|
let jumping = false;
|
|
let sneaking = false;
|
|
|
|
if (this.minecraft.hasInGameFocus()) {
|
|
if (Keyboard.isKeyDown("KeyR")) {
|
|
// this.respawn();
|
|
}
|
|
if (Keyboard.isKeyDown("KeyW")) {
|
|
moveForward++;
|
|
}
|
|
if (Keyboard.isKeyDown("KeyS")) {
|
|
moveForward--;
|
|
}
|
|
if (Keyboard.isKeyDown("KeyA")) {
|
|
moveStrafe++;
|
|
}
|
|
if (Keyboard.isKeyDown("KeyD")) {
|
|
moveStrafe--;
|
|
}
|
|
if (Keyboard.isKeyDown("Space")) {
|
|
jumping = true;
|
|
}
|
|
if (Keyboard.isKeyDown(this.minecraft.settings.keySprinting)) {
|
|
if (this.moveForward > 0 && !this.isSneaking() && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) {
|
|
this.sprinting = true;
|
|
|
|
this.updateFOVModifier();
|
|
}
|
|
}
|
|
if (Keyboard.isKeyDown(this.minecraft.settings.keyCrouching)) {
|
|
sneaking = true;
|
|
}
|
|
|
|
if (sneaking) {
|
|
moveStrafe = moveStrafe * 0.3;
|
|
moveForward = moveForward * 0.3;
|
|
}
|
|
}
|
|
|
|
this.moveForward = moveForward;
|
|
this.moveStrafing = moveStrafe;
|
|
|
|
this.jumping = jumping;
|
|
this.setSneaking(sneaking);
|
|
}
|
|
|
|
getEyeHeight() {
|
|
return this.isSneaking() ? 1.50 : 1.62;
|
|
}
|
|
|
|
updateFOVModifier() {
|
|
let value = 1.0;
|
|
|
|
if (this.sprinting) {
|
|
value += 1;
|
|
}
|
|
|
|
if (this.flying) {
|
|
value *= 1.1;
|
|
}
|
|
|
|
this.setFOVModifier((value - 1.0) * 10);
|
|
}
|
|
|
|
|
|
setFOVModifier(fov) {
|
|
this.prevFovModifier = this.fovModifier;
|
|
this.fovModifier = fov;
|
|
this.timeFovChanged = Date.now();
|
|
}
|
|
|
|
getFOVModifier() {
|
|
let timePassed = Date.now() - this.timeFovChanged;
|
|
let distance = this.prevFovModifier - this.fovModifier;
|
|
let duration = 100;
|
|
let progress = distance / duration * timePassed;
|
|
return timePassed > duration ? this.fovModifier : this.prevFovModifier - progress;
|
|
}
|
|
|
|
getBlockPosX() {
|
|
return this.x - (this.x < 0 ? 1 : 0);
|
|
}
|
|
|
|
getBlockPosY() {
|
|
return this.y - (this.y < 0 ? 1 : 0);
|
|
}
|
|
|
|
getBlockPosZ() {
|
|
return this.z - (this.z < 0 ? 1 : 0);
|
|
}
|
|
|
|
getPositionEyes(partialTicks) {
|
|
if (partialTicks === 1.0) {
|
|
return new Vector3(this.x, this.y + this.getEyeHeight(), this.z);
|
|
} else {
|
|
let x = this.prevX + (this.x - this.prevX) * partialTicks;
|
|
let y = this.prevY + (this.y - this.prevY) * partialTicks + this.getEyeHeight();
|
|
let z = this.prevZ + (this.z - this.prevZ) * partialTicks;
|
|
return new Vector3(x, y, z);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* interpolated look vector
|
|
*/
|
|
getLook(partialTicks) {
|
|
// TODO interpolation
|
|
return this.getVectorForRotation(this.rotationPitch, this.rotationYaw);
|
|
}
|
|
|
|
/**
|
|
* Creates a Vec3 using the pitch and yaw of the entities rotation.
|
|
*/
|
|
getVectorForRotation(pitch, yaw) {
|
|
let z = Math.cos(-yaw * 0.017453292 - Math.PI);
|
|
let x = Math.sin(-yaw * 0.017453292 - Math.PI);
|
|
let xz = -Math.cos(-pitch * 0.017453292);
|
|
let y = Math.sin(-pitch * 0.017453292);
|
|
return new Vector3(x * xz, y, z * xz);
|
|
}
|
|
|
|
rayTrace(blockReachDistance, partialTicks) {
|
|
let from = this.getPositionEyes(partialTicks);
|
|
let direction = this.getLook(partialTicks);
|
|
let to = from.addVector(direction.x * blockReachDistance, direction.y * blockReachDistance, direction.z * blockReachDistance);
|
|
return this.world.rayTraceBlocks(from, to);
|
|
}
|
|
|
|
isSprinting() {
|
|
return this.sprinting;
|
|
}
|
|
} |