diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js index 582c130..d6ce5b4 100644 --- a/src/js/net/minecraft/client/GameWindow.js +++ b/src/js/net/minecraft/client/GameWindow.js @@ -1,6 +1,6 @@ window.GameWindow = class { - constructor(renderer, canvasWrapperId) { + constructor(minecraft, renderer, canvasWrapperId) { this.renderer = renderer; this.canvasWrapperId = canvasWrapperId; @@ -30,6 +30,9 @@ window.GameWindow = class { // Mouse motion document.addEventListener('mousemove', event => this.onMouseMove(event), false); + // Mouse buttons + document.addEventListener('click', event => minecraft.onMouseClicked(event.button), false); + // Create keyboard Keyboard.create(); } @@ -51,7 +54,7 @@ window.GameWindow = class { } onMouseMove(event) { - this.mouseMotionX = -event.movementX; - this.mouseMotionY = event.movementY; + this.mouseMotionX = event.movementX; + this.mouseMotionY = -event.movementY; } } \ No newline at end of file diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index 0f12569..5908eac 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -5,7 +5,7 @@ window.Minecraft = class { */ constructor(canvasWrapperId) { this.worldRenderer = new WorldRenderer(this); - this.window = new GameWindow(this.worldRenderer, canvasWrapperId); + this.window = new GameWindow(this, this.worldRenderer, canvasWrapperId); this.timer = new Timer(20); this.frames = 0; @@ -66,6 +66,7 @@ window.Minecraft = class { } onRender(partialTicks) { + // Player rotation if (this.window.mouseLocked) { this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY); @@ -78,7 +79,35 @@ window.Minecraft = class { } onTick() { + // Tick the player this.player.onTick(); } + onMouseClicked(button) { + let hitResult = this.player.rayTrace(5, this.timer.partialTicks); + + // Destroy block + if (button === 0) { + if (hitResult != null) { + this.world.setBlockAt(hitResult.x, hitResult.y, hitResult.z, 0); + } + } + + // Place block + if (button === 2) { + if (hitResult != null) { + let x = hitResult.x + hitResult.face.x; + let y = hitResult.y + hitResult.face.y; + let z = hitResult.z + hitResult.face.z; + + let placedBoundingBox = new BoundingBox(x, y, z, x + 1, y + 1, z + 1); + + // Don't place blocks if the player is standing there + if (!placedBoundingBox.intersects(this.player.boundingBox)) { + this.world.setBlockAt(x, y, z, 1); + } + } + } + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/entity/Player.js b/src/js/net/minecraft/client/entity/Player.js index 2d200b1..bf0e2dc 100644 --- a/src/js/net/minecraft/client/entity/Player.js +++ b/src/js/net/minecraft/client/entity/Player.js @@ -182,7 +182,7 @@ window.Player = class { this.motionY = 0.42; if (this.sprinting) { - let radiansYaw = -this.yaw * (Math.PI / 180); + let radiansYaw = this.yaw * (Math.PI / 180) + Math.PI; this.motionX -= Math.sin(radiansYaw) * 0.2; this.motionZ += Math.cos(radiansYaw) * 0.2; } @@ -281,7 +281,7 @@ window.Player = class { up = up * distance; forward = forward * distance; - let yawRadians = -this.yaw * (Math.PI / 180); + let yawRadians = this.yaw * (Math.PI / 180) + Math.PI; let sin = Math.sin(yawRadians); let cos = Math.cos(yawRadians); @@ -473,4 +473,41 @@ window.Player = class { 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.pitch, this.yaw); + } + + /** + * 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); + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index cc91005..4e953aa 100644 --- a/src/js/net/minecraft/client/render/BlockRenderer.js +++ b/src/js/net/minecraft/client/render/BlockRenderer.js @@ -41,7 +41,7 @@ window.BlockRenderer = class { let textureIndex = block.getTextureForFace(face); let minU = (textureIndex % 16) / 16.0; let maxU = minU + (16 / 256); - let minV = Math.round(textureIndex / 16); + let minV = Math.floor(textureIndex / 16); let maxV = minV + (16 / 256); // Flip V @@ -65,25 +65,25 @@ window.BlockRenderer = class { this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV); this.addBlockCorner(world, face, minX, maxY, maxZ, minU, maxV); } - if (face === EnumBlockFace.EAST) { + if (face === EnumBlockFace.NORTH) { this.addBlockCorner(world, face, minX, maxY, minZ, maxU, minV); this.addBlockCorner(world, face, maxX, maxY, minZ, minU, minV); this.addBlockCorner(world, face, maxX, minY, minZ, minU, maxV); this.addBlockCorner(world, face, minX, minY, minZ, maxU, maxV); } - if (face === EnumBlockFace.WEST) { + if (face === EnumBlockFace.SOUTH) { this.addBlockCorner(world, face, minX, maxY, maxZ, minU, minV); this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV); this.addBlockCorner(world, face, maxX, minY, maxZ, maxU, maxV); this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, minV); } - if (face === EnumBlockFace.NORTH) { + if (face === EnumBlockFace.WEST) { this.addBlockCorner(world, face, minX, maxY, maxZ, maxU, minV); this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV); this.addBlockCorner(world, face, minX, minY, minZ, minU, maxV); this.addBlockCorner(world, face, minX, minY, maxZ, maxU, maxV); } - if (face === EnumBlockFace.SOUTH) { + if (face === EnumBlockFace.EAST) { this.addBlockCorner(world, face, maxX, minY, maxZ, minU, maxV); this.addBlockCorner(world, face, maxX, minY, minZ, maxU, maxV); this.addBlockCorner(world, face, maxX, maxY, minZ, maxU, minV); diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js index 0b12ef1..3527858 100644 --- a/src/js/net/minecraft/client/render/WorldRenderer.js +++ b/src/js/net/minecraft/client/render/WorldRenderer.js @@ -58,8 +58,8 @@ window.WorldRenderer = class { let player = this.minecraft.player; // Rotation - this.camera.rotation.y = player.yaw * (Math.PI / 180); - this.camera.rotation.x = player.pitch * (Math.PI / 180); + this.camera.rotation.y = -player.yaw * (Math.PI / 180) + Math.PI; + this.camera.rotation.x = -player.pitch * (Math.PI / 180); // Position let x = player.prevX + (player.x - player.prevX) * partialTicks; @@ -90,21 +90,14 @@ window.WorldRenderer = class { renderChunks(renderer, partialTicks) { let world = this.minecraft.world; - const xKeys = Object.keys(world.chunks) - for (let x = 0; x < xKeys.length; x++) { + for(let i in world.chunks) { + let chunk = world.chunks[i]; - let zArray = world.chunks[xKeys[x]]; - const zKeys = Object.keys(zArray) + for (let y = 0; y < chunk.sections.length; y++) { + let section = chunk.sections[y]; - for (let z = 0; z < zKeys.length; z++) { - let chunk = zArray[zKeys[z]]; - - for (let y = 0; y < chunk.sections.length; y++) { - let section = chunk.sections[y]; - - if (section.dirty) { - section.rebuild(renderer); - } + if (section.dirty) { + section.rebuild(renderer); } } } diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index 7df66a9..19b7617 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -22,15 +22,15 @@ window.World = class { return y < 0 || y > World.TOTAL_HEIGHT ? null : chunk.getSection(y >> 4); } - getCollisionBoxes(aabb) { + getCollisionBoxes(region) { let boundingBoxList = []; - let minX = MathHelper.floor_double(aabb.minX); - let maxX = MathHelper.floor_double(aabb.maxX + 1.0); - let minY = MathHelper.floor_double(aabb.minY); - let maxY = MathHelper.floor_double(aabb.maxY + 1.0); - let minZ = MathHelper.floor_double(aabb.minZ); - let maxZ = MathHelper.floor_double(aabb.maxZ + 1.0); + let minX = MathHelper.floor_double(region.minX); + let maxX = MathHelper.floor_double(region.maxX + 1.0); + let minY = MathHelper.floor_double(region.minY); + let maxY = MathHelper.floor_double(region.maxY + 1.0); + let minZ = MathHelper.floor_double(region.minZ); + let maxZ = MathHelper.floor_double(region.maxZ + 1.0); for (let x = minX; x < maxX; x++) { for (let y = minY; y < maxY; y++) { @@ -64,16 +64,15 @@ window.World = class { return chunkSection == null ? 0 : chunkSection.getBlockAt(x & 15, y & 15, z & 15); } - getChunkAt(x, z) { - let zArray = this.chunks[x]; - if (typeof zArray === 'undefined') { - zArray = this.chunks[x] = []; - } + getChunkSectionAt(chunkX, layerY, chunkZ) { + return this.getChunkAt(chunkX, chunkZ).getSection(layerY); + } - let chunk = zArray[z]; + getChunkAt(x, z) { + let index = x + (z << 16); + let chunk = this.chunks[index]; if (typeof chunk === 'undefined') { - chunk = new Chunk(this, x, z); - this.chunks[x][z] = chunk; + this.chunks[index] = chunk = new Chunk(this, x, z); this.group.add(chunk.group); } return chunk; @@ -99,10 +98,123 @@ window.World = class { for (let x = minX; x <= maxX; x++) { for (let y = minY; y <= maxY; y++) { for (let z = minZ; z <= maxZ; z++) { - this.getChunkAt(x, y, z).queueForRebuild(); + this.getChunkSectionAt(x, y, z).queueForRebuild(); } } } } + rayTraceBlocks(from, to) { + let toX = MathHelper.floor_double(to.x); + let toY = MathHelper.floor_double(to.y); + let toZ = MathHelper.floor_double(to.z); + + let x = MathHelper.floor_double(from.x); + let y = MathHelper.floor_double(from.y); + let z = MathHelper.floor_double(from.z); + + let blockId = this.getBlockAt(x, y, z); + let block = Block.getById(blockId); + let hit = block == null ? null : block.collisionRayTrace(x, y, z, from, to); + + if (hit != null) { + return hit; + } + + let lastHit = null; + + let counter = 200; + while (counter-- >= 0) { + if (x === toX && y === toY && z === toZ) { + return lastHit; + } + + let hitX = true; + let hitY = true; + let hitZ = true; + + let nearestX1 = 999.0; + let nearestY1 = 999.0; + let nearestZ1 = 999.0; + + if (toX > x) { + nearestX1 = x + 1.0; + } else if (toX < x) { + nearestX1 = x; + } else { + hitX = false; + } + + if (toY > y) { + nearestY1 = y + 1.0; + } else if (toY < y) { + nearestY1 = y; + } else { + hitY = false; + } + + if (toZ > z) { + nearestZ1 = z + 1.0; + } else if (toZ < z) { + nearestZ1 = z; + } else { + hitZ = false; + } + + let nearestX = 999.0; + let nearestY = 999.0; + let nearestZ = 999.0; + + let diffX = to.x - from.x; + let diffY = to.y - from.y; + let diffZ = to.z - from.z; + + if (hitX) { + nearestX = (nearestX1 - from.x) / diffX; + } + if (hitY) { + nearestY = (nearestY1 - from.y) / diffY; + } + if (hitZ) { + nearestZ = (nearestZ1 - from.z) / diffZ; + } + + if (nearestX === -0.0) { + nearestX = -1.0E-4; + } + if (nearestY === -0.0) { + nearestY = -1.0E-4; + } + if (nearestZ === -0.0) { + nearestZ = -1.0E-4; + } + + let face; + if (nearestX < nearestY && nearestX < nearestZ) { + face = toX > x ? EnumBlockFace.WEST : EnumBlockFace.EAST; + from = new Vector3(nearestX1, from.y + diffY * nearestX, from.z + diffZ * nearestX); + } else if (nearestY < nearestZ) { + face = toY > y ? EnumBlockFace.BOTTOM : EnumBlockFace.TOP; + from = new Vector3(from.x + diffX * nearestY, nearestY1, from.z + diffZ * nearestY); + } else { + face = toZ > z ? EnumBlockFace.NORTH : EnumBlockFace.SOUTH; + from = new Vector3(from.x + diffX * nearestZ, from.y + diffY * nearestZ, nearestZ1); + } + + x = MathHelper.floor_double(from.x) - (face === EnumBlockFace.EAST ? 1 : 0); + y = MathHelper.floor_double(from.y) - (face === EnumBlockFace.TOP ? 1 : 0); + z = MathHelper.floor_double(from.z) - (face === EnumBlockFace.SOUTH ? 1 : 0); + + let blockId = this.getBlockAt(x, y, z); + let block = Block.getById(blockId); + let hit = block == null ? null : block.collisionRayTrace(x, y, z, from, to); + if (hit != null) { + return hit; + } + } + + return lastHit; + + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/block/Block.js b/src/js/net/minecraft/client/world/block/Block.js index 1fa9b0c..a25b934 100644 --- a/src/js/net/minecraft/client/world/block/Block.js +++ b/src/js/net/minecraft/client/world/block/Block.js @@ -51,6 +51,117 @@ window.Block = class { return this.boundingBox; } + collisionRayTrace(x, y, z, start, end) { + start = start.addVector(-x, -y, -z); + end = end.addVector(-x, -y, -z); + + let vec3 = start.getIntermediateWithXValue(end, this.boundingBox.minX); + let vec31 = start.getIntermediateWithXValue(end, this.boundingBox.maxX); + let vec32 = start.getIntermediateWithYValue(end, this.boundingBox.minY); + let vec33 = start.getIntermediateWithYValue(end, this.boundingBox.maxY); + let vec34 = start.getIntermediateWithZValue(end, this.boundingBox.minZ); + let vec35 = start.getIntermediateWithZValue(end, this.boundingBox.maxZ); + + if (!this.isVecInsideYZBounds(vec3)) { + vec3 = null; + } + + if (!this.isVecInsideYZBounds(vec31)) { + vec31 = null; + } + + if (!this.isVecInsideXZBounds(vec32)) { + vec32 = null; + } + + if (!this.isVecInsideXZBounds(vec33)) { + vec33 = null; + } + + if (!this.isVecInsideXYBounds(vec34)) { + vec34 = null; + } + + if (!this.isVecInsideXYBounds(vec35)) { + vec35 = null; + } + + let vec36 = null; + if (vec3 != null && (vec36 == null || start.squareDistanceTo(vec3) < start.squareDistanceTo(vec36))) { + vec36 = vec3; + } + if (vec31 != null && (vec36 == null || start.squareDistanceTo(vec31) < start.squareDistanceTo(vec36))) { + vec36 = vec31; + } + if (vec32 != null && (vec36 == null || start.squareDistanceTo(vec32) < start.squareDistanceTo(vec36))) { + vec36 = vec32; + } + if (vec33 != null && (vec36 == null || start.squareDistanceTo(vec33) < start.squareDistanceTo(vec36))) { + vec36 = vec33; + } + if (vec34 != null && (vec36 == null || start.squareDistanceTo(vec34) < start.squareDistanceTo(vec36))) { + vec36 = vec34; + } + if (vec35 != null && (vec36 == null || start.squareDistanceTo(vec35) < start.squareDistanceTo(vec36))) { + vec36 = vec35; + } + + if (vec36 == null) { + return null; + } + + let face = null; + if (vec36 === vec3) { + face = EnumBlockFace.WEST; + } + if (vec36 === vec31) { + face = EnumBlockFace.EAST; + } + if (vec36 === vec32) { + face = EnumBlockFace.BOTTOM; + } + if (vec36 === vec33) { + face = EnumBlockFace.TOP; + } + if (vec36 === vec34) { + face = EnumBlockFace.NORTH; + } + if (vec36 === vec35) { + face = EnumBlockFace.SOUTH; + } + return new MovingObjectPosition(vec36.addVector(x, y, z), face, x, y, z); + } + + /** + * Checks if a vector is within the Y and Z bounds of the block. + */ + isVecInsideYZBounds(point) { + return point == null ? false : point.y >= this.boundingBox.minY + && point.y <= this.boundingBox.maxY + && point.z >= this.boundingBox.minZ + && point.z <= this.boundingBox.maxZ; + } + + /** + * Checks if a vector is within the X and Z bounds of the block. + */ + isVecInsideXZBounds(point) { + return point == null ? false : point.x >= this.boundingBox.minX + && point.x <= this.boundingBox.maxX + && point.z >= this.boundingBox.minZ + && point.z <= this.boundingBox.maxZ; + } + + /** + * Checks if a vector is within the X and Y bounds of the block. + */ + isVecInsideXYBounds(point) { + return point == null ? false : point.x >= this.boundingBox.minX + && point.x <= this.boundingBox.maxX + && point.y >= this.boundingBox.minY + && point.y <= this.boundingBox.maxY; + } + static getById(typeId) { return Block.blocks[typeId]; } diff --git a/src/js/net/minecraft/util/BoundingBox.js b/src/js/net/minecraft/util/BoundingBox.js index b491c83..9dd29f6 100644 --- a/src/js/net/minecraft/util/BoundingBox.js +++ b/src/js/net/minecraft/util/BoundingBox.js @@ -243,7 +243,6 @@ window.BoundingBox = class { this.maxZ += z; } - /** * Create a new bounding box with the given offset * diff --git a/src/js/net/minecraft/util/EnumBlockFace.js b/src/js/net/minecraft/util/EnumBlockFace.js index 08a8e6a..4183097 100644 --- a/src/js/net/minecraft/util/EnumBlockFace.js +++ b/src/js/net/minecraft/util/EnumBlockFace.js @@ -38,8 +38,8 @@ window.EnumBlockFace = class { let c = window.EnumBlockFace; c.TOP = new EnumBlockFace(0, 1, 0); c.BOTTOM = new EnumBlockFace(0, -1, 0); - c.NORTH = new EnumBlockFace(-1, 0, 0); - c.EAST = new EnumBlockFace(0, 0, -1); - c.SOUTH = new EnumBlockFace(1, 0, 0); - c.WEST = new EnumBlockFace(0, 0, 1); + c.NORTH = new EnumBlockFace(0, 0, -1); + c.EAST = new EnumBlockFace(1, 0, 0); + c.SOUTH = new EnumBlockFace(0, 0, 1); + c.WEST = new EnumBlockFace(-1, 0, 0); } diff --git a/src/js/net/minecraft/util/MovingObjectPosition.js b/src/js/net/minecraft/util/MovingObjectPosition.js new file mode 100644 index 0000000..d24d496 --- /dev/null +++ b/src/js/net/minecraft/util/MovingObjectPosition.js @@ -0,0 +1,11 @@ +window.MovingObjectPosition = class { + + constructor(vector, face, x, y, z) { + this.vector = vector; + this.face = face; + + this.x = x; + this.y = y; + this.z = z; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/util/Timer.js b/src/js/net/minecraft/util/Timer.js index a4c32b5..b0ef972 100644 --- a/src/js/net/minecraft/util/Timer.js +++ b/src/js/net/minecraft/util/Timer.js @@ -1,49 +1,35 @@ window.Timer = class { + static MS_PER_SECOND = 1000; + static MAX_MS_PER_UPDATE = 1000; + static MAX_TICKS_PER_UPDATE = 100; + /** * Timer to control the tick speed independently of the framerate * * @param ticksPerSecond Amount of ticks per second */ constructor(ticksPerSecond) { - this.MS_PER_SECOND = 1000; - this.MAX_MS_PER_UPDATE = 1000; - this.MAX_TICKS_PER_UPDATE = 100; - - /** - * Amount of ticks per second - */ + // Amount of ticks per second this.ticksPerSecond = ticksPerSecond; - /** - * Last time updated in nano seconds - */ - this.lastTime = this._nanoTime(); + // Last time updated in milliseconds + this.lastTime = Date.now(); - /** - * Scale the tick speed - */ + // Scale the tick speed this.timeScale = 1.0; - /** - * Framerate of the advanceTime update - */ + // Framerate of the advanceTime update this.fps = 0.0; - /** - * Passed time since last game update - */ + // Passed time since last game update this.passedTime = 0.0; - /** - * The amount of ticks for the current game update. - * It's the passed time as an integer - */ + // The amount of ticks for the current game update. + // It's the passed time as an integer this.ticks = 0; - /** - * The overflow of the current tick, caused by casting the passed time to an integer - */ + // The overflow of the current tick, caused by casting the passed time to an integer this.partialTicks = 0; } @@ -53,7 +39,7 @@ window.Timer = class { * Call this function in the main render loop of the game */ advanceTime() { - let now = this._nanoTime(); + let now = Date.now(); let passedMs = now - this.lastTime; // Store nano time of this update @@ -61,24 +47,20 @@ window.Timer = class { // Maximum and minimum passedMs = Math.max(0, passedMs); - passedMs = Math.min(this.MAX_MS_PER_UPDATE, passedMs); + passedMs = Math.min(Timer.MAX_MS_PER_UPDATE, passedMs); // Calculate fps - this.fps = this.MS_PER_SECOND / passedMs; + this.fps = Timer.MS_PER_SECOND / passedMs; // Calculate passed time and ticks - this.passedTime += passedMs * this.timeScale * this.ticksPerSecond / this.MS_PER_SECOND; + this.passedTime += passedMs * this.timeScale * this.ticksPerSecond / Timer.MS_PER_SECOND; this.ticks = parseInt(this.passedTime); // Maximum ticks per update - this.ticks = Math.min(this.MAX_TICKS_PER_UPDATE, this.ticks); + this.ticks = Math.min(Timer.MAX_TICKS_PER_UPDATE, this.ticks); // Calculate the overflow of the current tick this.passedTime -= this.ticks; this.partialTicks = this.passedTime; } - - _nanoTime() { - return Date.now(); - } } diff --git a/src/js/net/minecraft/util/Vector3.js b/src/js/net/minecraft/util/Vector3.js new file mode 100644 index 0000000..43dc77f --- /dev/null +++ b/src/js/net/minecraft/util/Vector3.js @@ -0,0 +1,72 @@ +window.Vector3 = class { + + constructor(x = 0, y = 0, z = 0) { + this.x = x; + this.y = y; + this.z = z; + } + + + addVector(x, y, z) { + return new Vector3(this.x + x, this.y + y, this.z + z); + } + + squareDistanceTo(vec) { + let d0 = vec.x - this.x; + let d1 = vec.y - this.y; + let d2 = vec.z - this.z; + return d0 * d0 + d1 * d1 + d2 * d2; + } + + /** + * Returns a new vector with x value equal to the second parameter, along the line between this vector and the + * passed in vector, or null if not possible. + */ + getIntermediateWithXValue(vec, x) { + let d0 = vec.x - this.x; + let d1 = vec.y - this.y; + let d2 = vec.z - this.z; + + if (d0 * d0 < 1.0000000116860974E-7) { + return null; + } else { + let d3 = (x - this.x) / d0; + return d3 >= 0.0 && d3 <= 1.0 ? new Vector3(this.x + d0 * d3, this.y + d1 * d3, this.z + d2 * d3) : null; + } + } + + /** + * Returns a new vector with y value equal to the second parameter, along the line between this vector and the + * passed in vector, or null if not possible. + */ + getIntermediateWithYValue(vec, y) { + let d0 = vec.x - this.x; + let d1 = vec.y - this.y; + let d2 = vec.z - this.z; + + if (d1 * d1 < 1.0000000116860974E-7) { + return null; + } else { + let d3 = (y - this.y) / d1; + return d3 >= 0.0 && d3 <= 1.0 ? new Vector3(this.x + d0 * d3, this.y + d1 * d3, this.z + d2 * d3) : null; + } + } + + /** + * Returns a new vector with z value equal to the second parameter, along the line between this vector and the + * passed in vector, or null if not possible. + */ + getIntermediateWithZValue(vec, z) { + let d0 = vec.x - this.x; + let d1 = vec.y - this.y; + let d2 = vec.z - this.z; + + if (d2 * d2 < 1.0000000116860974E-7) { + return null; + } else { + let d3 = (z - this.z) / d2; + return d3 >= 0.0 && d3 <= 1.0 ? new Vector3(this.x + d0 * d3, this.y + d1 * d3, this.z + d2 * d3) : null; + } + } + +} \ No newline at end of file diff --git a/src/start.js b/src/start.js index ffc56bb..036ab47 100644 --- a/src/start.js +++ b/src/start.js @@ -49,6 +49,8 @@ loadScripts([ // Minecraft Source "src/js/net/minecraft/util/EnumBlockFace.js", "src/js/net/minecraft/util/Timer.js", + "src/js/net/minecraft/util/Vector3.js", + "src/js/net/minecraft/util/MovingObjectPosition.js", "src/js/net/minecraft/util/MathHelper.js", "src/js/net/minecraft/util/BoundingBox.js", "src/js/net/minecraft/util/Keyboard.js",