diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js index aaff7f4..92b2cd8 100644 --- a/src/js/net/minecraft/client/GameWindow.js +++ b/src/js/net/minecraft/client/GameWindow.js @@ -12,7 +12,7 @@ window.GameWindow = class { // Stats this.stats = new Stats() - this.stats.showPanel(0); + this.stats.showPanel(1); wrapper.appendChild(this.stats.dom); // Add web renderer canvas to wrapper diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index ece1e13..7a2acd1 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -81,6 +81,8 @@ window.Minecraft = class { // Render the game this.worldRenderer.render(partialTicks); + + while (this.world.updateLights()) ; } onTick() { @@ -99,7 +101,6 @@ window.Minecraft = class { if (button === 0) { if (hitResult != null) { this.world.setBlockAt(hitResult.x, hitResult.y, hitResult.z, 0); - this.world.updateBlockLightAt(hitResult.x, hitResult.y, hitResult.z); } } @@ -125,7 +126,6 @@ window.Minecraft = class { // Don't place blocks if the player is standing there if (!placedBoundingBox.intersects(this.player.boundingBox)) { this.world.setBlockAt(x, y, z, this.pickedBlock); - this.world.updateBlockLightAt(x, y, z); } } } diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index 32e30ec..b402af4 100644 --- a/src/js/net/minecraft/client/render/BlockRenderer.js +++ b/src/js/net/minecraft/client/render/BlockRenderer.js @@ -1,6 +1,6 @@ window.BlockRenderer = class { - static CLASSIC_LIGHTNING = false; + static CLASSIC_LIGHTNING = true; constructor(worldRenderer) { this.worldRenderer = worldRenderer; @@ -125,7 +125,7 @@ window.BlockRenderer = class { if (typeId === 0 || Block.getById(typeId).isTransparent()) { // Sum up the light levels - totalLightLevel += world.getLightAt(x + offsetX, y + offsetY, z + offsetZ); + totalLightLevel += world.getTotalLightAt(x + offsetX, y + offsetY, z + offsetZ); totalBlocks++; } } diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js index 595a884..8a040e6 100644 --- a/src/js/net/minecraft/client/render/WorldRenderer.js +++ b/src/js/net/minecraft/client/render/WorldRenderer.js @@ -103,8 +103,7 @@ window.WorldRenderer = class { renderChunks(cameraChunkX, cameraChunkZ) { let world = this.minecraft.world; - for (let i in world.chunks) { - let chunk = world.chunks[i]; + for (let [index, chunk] of world.chunks) { let distanceX = Math.abs(cameraChunkX - chunk.x); let distanceZ = Math.abs(cameraChunkZ - chunk.z); diff --git a/src/js/net/minecraft/client/world/Chunk.js b/src/js/net/minecraft/client/world/Chunk.js index 428c061..3d51e97 100644 --- a/src/js/net/minecraft/client/world/Chunk.js +++ b/src/js/net/minecraft/client/world/Chunk.js @@ -18,10 +18,141 @@ window.Chunk = class { this.sections[y] = section; this.group.add(section.group); } + + // Create height map + this.heightMap = []; } setBlockAt(x, y, z, typeId) { - this.getSection(y >> 4).setBlockAt(x, y & 15, z, typeId); + let section = this.getSection(y >> 4); + let prevTypeId = section.getBlockAt(x, y & 15, z); + if (prevTypeId === typeId) { + return; + } + + // Update block type id + section.setBlockAt(x, y & 15, z, typeId); + + let block = Block.getById(typeId); + let heightLevel = this.heightMap[z << 4 | x] & 0xff; + + if (typeId !== 0 && block.isSolid()) { + if (y >= heightLevel) { + // Update height map if it is the new highest block now + this.updateHeightMap(x, y + 1, z); + } + } else if (y === heightLevel - 1) { + // Update height map if it is below the highest block because it could block the sun + this.updateHeightMap(x, y, z); + } + + // Update light at block + //this.world.updateLight(EnumSkyBlock.SKY, x, y, z, x, y, z); + //this.world.updateLight(EnumSkyBlock.BLOCK, x, y, z, x, y, z); + + // Notify neighbors + //this.notifyNeighbors(x, z); + } + + notifyNeighbors(x, z) { + let height = this.getHeightAt(x, z); + let totalX = this.x * 16 + x; + let totalZ = this.z * 16 + z; + + this.updateSkyLight(totalX - 1, totalZ, height); + this.updateSkyLight(totalX + 1, totalZ, height); + this.updateSkyLight(totalX, totalZ - 1, height); + this.updateSkyLight(totalX, totalZ + 1, height); + } + + updateSkyLight(x, z, y) { + let height = this.world.getHeightAt(x, z); + if (height > y) { + this.world.updateLight(EnumSkyBlock.SKY, x, y, z, x, height, z); + } else if (height < y) { + this.world.updateLight(EnumSkyBlock.SKY, x, height, z, x, y, z); + } + } + + getBlockAt(x, y, z) { + return this.getSection(y >> 4).getBlockAt(x, y & 15, z); + } + + isHighestBlock(x, y, z) { + return y >= (this.heightMap[z << 4 | x] & 0xff); + } + + getHeightAt(x, z) { + return this.heightMap[z << 4 | x] & 0xff; + } + + updateHeightMap(x, y, z) { + let currentHighestY = this.heightMap[z << 4 | x] & 0xff; + let highestY = currentHighestY; + if (y > currentHighestY) { + highestY = y; + } + + // Find new highest blocks + while (highestY > 0) { + let typeId = this.getBlockAt(x, highestY, z); + let block = Block.getById(typeId); + if (typeId !== 0 && block.isSolid()) { + break; + } + highestY--; + } + + // Check if highest block changed + if (highestY === currentHighestY) { + return; + } + + // Save in height map + this.heightMap[z << 4 | x] = highestY; + + + let totalX = this.x * 16 + x; + let totalZ = this.z * 16 + z; + + if (highestY < currentHighestY) { + for (let hy = highestY; hy < currentHighestY; hy++) { + this.getSection(hy >> 4).setLightAt(EnumSkyBlock.SKY, x, hy, z, 15); + } + } else { + this.world.updateLight(EnumSkyBlock.SKY, totalX, currentHighestY, totalZ, totalX, highestY, totalZ); + + for (let hy = currentHighestY; hy < highestY; hy++) { + this.getSection(hy >> 4).setLightAt(EnumSkyBlock.SKY, x, hy, z, 0); + } + + } + + let lightLevel = 15; + let currentY = highestY; + while (currentY > 0 && lightLevel > 0) { + currentY--; + + let typeId = this.getBlockAt(x, currentY, z); + let block = Block.getById(typeId); + + // Reduce light level by opacity + if (typeId !== 0) { + lightLevel *= (1 - block.getOpacity()); + } + + // Min light level + if (lightLevel < 0) { + lightLevel = 0; + } + + // Update light level + this.getSection(currentY >> 4).setLightAt(EnumSkyBlock.SKY, x & 15, currentY, z & 15, lightLevel); + } + + if (currentY !== highestY) { + this.world.updateLight(EnumSkyBlock.SKY, x - 1, currentY, z - 1, x + 1, currentY, z + 1); + } } getSection(y) { diff --git a/src/js/net/minecraft/client/world/ChunkSection.js b/src/js/net/minecraft/client/world/ChunkSection.js index abe4e75..90a3779 100644 --- a/src/js/net/minecraft/client/world/ChunkSection.js +++ b/src/js/net/minecraft/client/world/ChunkSection.js @@ -24,15 +24,16 @@ window.ChunkSection = class { this.blocks = []; this.blockLight = []; + this.skyLight = []; // Fill chunk with air and light - for (let lightX = 0; lightX < ChunkSection.SIZE; lightX++) { - for (let lightY = 0; lightY < ChunkSection.SIZE; lightY++) { - for (let lightZ = 0; lightZ < ChunkSection.SIZE; lightZ++) { - let index = lightY << 8 | lightZ << 4 | lightX; - + for (let tX = 0; tX < ChunkSection.SIZE; tX++) { + for (let tY = 0; tY < ChunkSection.SIZE; tY++) { + for (let tZ = 0; tZ < ChunkSection.SIZE; tZ++) { + let index = tY << 8 | tZ << 4 | tX; this.blocks[index] = 0; - this.blockLight[index] = 15; + this.blockLight[index] = 0; + this.skyLight[index] = 0; } } } @@ -81,14 +82,30 @@ window.ChunkSection = class { this.blocks[index] = typeId; } - setLightAt(x, y, z, lightLevel) { + setLightAt(sourceType, x, y, z, lightLevel) { let index = y << 8 | z << 4 | x; this.blockLight[index] = lightLevel; } - getLightAt(x, y, z) { + getTotalLightAt(x, y, z) { let index = y << 8 | z << 4 | x; - return this.blockLight[index]; + let skyLight = this.skyLight[index]; + let blockLight = this.blockLight[index]; + if (blockLight > skyLight) { + skyLight = blockLight; + } + return skyLight; + } + + getLightAt(sourceType, x, y, z) { + let index = y << 8 | z << 4 | x; + if (sourceType === EnumSkyBlock.SKY) { + return this.skyLight[index]; + } + if (sourceType === EnumSkyBlock.Block) { + return this.blockLight[index]; + } + return 0; } isEmpty() { diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index 2ea1a37..760c867 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -5,32 +5,19 @@ window.World = class { constructor() { this.group = new THREE.Object3D(); this.group.matrixAutoUpdate = false; - this.chunks = []; + this.chunks = new Map(); // Load world this.generator = new WorldGenerator(this, Date.now() % 100000); this.lightUpdateQueue = []; + + this.lightUpdateProcesses = 0; + this.lightUpdates = 0; } onTick() { - // Handle 128 light updates per tick - for (let i = 0; i < 128; i++) { - // Light updates - if (this.lightUpdateQueue.length !== 0) { - - // Get next position to update - let positionIndex = this.lightUpdateQueue.shift(); - if (positionIndex != null) { - let z = positionIndex >> 16; - let x = positionIndex - (z << 16); - this.updateBlockLightsAtXZ(x, z); - } else { - break; - } - } - } } loadChunk(chunk) { @@ -71,6 +58,113 @@ window.World = class { return boundingBoxList; } + updateLight(sourceType, x1, y1, z1, x2, y2, z2, notifyNeighbor = true) { + if (this.lightUpdates >= 50) { + return; + } + + this.lightUpdates++; + + let size = this.lightUpdateQueue.length; + + if (notifyNeighbor) { + let max = 4; + if (max > size) { + max = size; + } + + for (let i = 0; i < max; i++) { + let meta = this.lightUpdateQueue[size - i - 1]; + if (meta.type === sourceType && meta.isOutsideOf(x1, y1, z1, x2, y2, z2)) { + this.lightUpdates--; + return; + } + } + } + + // Push light update to queue + this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2)); + if (this.lightUpdateQueue.length > 0x186a0) { + this.lightUpdateQueue = []; + } + this.lightUpdates--; + } + + neighborLightPropagationChanged(sourceType, x, y, z, lightLevel) { + if (sourceType === EnumSkyBlock.SKY) { + if (this.isHighestBlock(x, y, z)) { + lightLevel = 15; + } + } else if (sourceType === EnumSkyBlock.BLOCK) { + let typeId = this.getBlockAt(x, y, z); + let block = Block.getById(typeId); + let blockLight = block.getLightValue(); + + if (blockLight > lightLevel) { + lightLevel = blockLight; + } + } + if (this.getSavedLightValue(sourceType, x, y, z) !== lightLevel) { + this.updateLight(sourceType, x, y, z, x, y, z); + } + } + + updateLights() { + if (this.lightUpdateProcesses >= 50) { + return false; + } + this.lightUpdateProcesses++; + + // Update lights in queue + let i = 5000; + while (this.lightUpdateQueue.length > 0) { + if (i <= 0) { + return true; + } + this.lightUpdateQueue.shift().updateBlockLightning(this); + i--; + } + + this.lightUpdateProcesses--; + return false; + } + + getHeightAt(x, z) { + return this.getChunkAt(x >> 4, z >> 4).getHeightAt(x & 15, z & 15); + } + + isHighestBlock(x, y, z) { + let chunk = this.getChunkAt(x >> 4, z >> 4) + return y >= chunk.getHeightAt(x & 15, z & 15); + } + + getTotalLightAt(x, y, z) { + if (y < 0) { + return 15; + } + + let section = this.getChunkSectionAt(x >> 4, y >> 4, z >> 4) + return section.getTotalLightAt(x & 15, y & 15, z & 15); + } + + getSavedLightValue(sourceType, x, y, z) { + if (y < 0) { + return 15; + } + + let section = this.getChunkSectionAt(x >> 4, y >> 4, z >> 4) + return section.getLightAt(sourceType, x & 15, y & 15, z & 15); + } + + setLightAt(sourceType, x, y, z, lightLevel) { + if (y < 0) { + return; + } + + let section = this.getChunkSectionAt(x >> 4, y >> 4, z >> 4) + section.setLightAt(sourceType, x & 15, y & 15, z & 15, lightLevel); + } + isSolidBlockAt(x, y, z) { let typeId = this.getBlockAt(x, y, z); return typeId !== 0 && Block.getById(typeId).isSolid(); @@ -82,11 +176,10 @@ window.World = class { } setBlockAt(x, y, z, type) { - let chunkSection = this.getChunkAtBlock(x, y, z); - if (chunkSection != null) { - chunkSection.setBlockAt(x & 15, y & 15, z & 15, type); - } + let chunk = this.getChunkAt(x >> 4, z >> 4); + chunk.setBlockAt(x & 15, y, z & 15, type); + // Rebuild chunk this.onBlockChanged(x, y, z); } @@ -105,127 +198,14 @@ window.World = class { getChunkAt(x, z) { let index = x + (z << 16); - let chunk = this.chunks[index]; + let chunk = this.chunks.get(index); if (typeof chunk === 'undefined') { - this.chunks[index] = chunk = new Chunk(this, x, z); + this.chunks.set(index, chunk = new Chunk(this, x, z)); this.group.add(chunk.group); } return chunk; } - getHighestBlockYAt(x, z) { - for (let y = World.TOTAL_HEIGHT; y > 0; y--) { - if (this.isSolidBlockAt(x, y, z)) { - return y; - } - } - return 0; - } - - updateBlockLightAt(x, y, z) { - // Calculate brightness for target block - let lightLevel = this.isHighestBlockAt(x, y, z) ? 15 : this.calculateLightAt(x, y, z); - - // Update target block light - this.getChunkAtBlock(x, y, z).setLightAt(x & 15, y & 15, z & 15, lightLevel); - - // Update block lights below the target block and the surrounding blocks - for (let offsetX = -1; offsetX <= 1; offsetX++) { - for (let offsetZ = -1; offsetZ <= 1; offsetZ++) { - this.updateBlockLightsAtXZ(x + offsetX, z + offsetZ); - } - } - } - - updateBlockLightsAtXZ(x, z) { - let lightChanged = false; - let skyLevel = 15; - - // Scan from the top to the bottom - for (let y = World.TOTAL_HEIGHT; y >= 0; y--) { - if (!this.isTransparentBlockAt(x, y, z)) { - // Sun is blocked because of solid block - skyLevel = 0; - } else { - // Get opacity of this block - let typeId = this.getBlockAt(x, y, z); - let translucence = typeId === 0 ? 1.0 : 1.0 - Block.getById(typeId).getOpacity(); - - // Decrease strength of the skylight by the opacity of the block - skyLevel *= translucence; - - // Get previous block light - let prevBlockLight = this.getLightAt(x, y, z); - - // Combine skylight with the calculated block light and decrease strength by the opacity of the block - let blockLight = Math.floor(Math.max(skyLevel, this.calculateLightAt(x, y, z)) * translucence); - - // Did one of the light change inside of the range? - if (prevBlockLight !== blockLight) { - lightChanged = true; - } - - // Apply the new light to the block - this.setLightAt(x, y, z, blockLight); - } - } - - // Chain reaction, update next affected blocks - if (lightChanged && this.lightUpdateQueue.length < 512) { - for (let offsetX = -1; offsetX <= 1; offsetX++) { - for (let offsetZ = -1; offsetZ <= 1; offsetZ++) { - let positionIndex = (x + offsetX) + ((z + offsetZ) << 16); - - // Add block range to update queue - if (!this.lightUpdateQueue.includes(positionIndex)) { - this.lightUpdateQueue.push(positionIndex); - } - } - } - } - } - - setLightAt(x, y, z, light) { - let chunkSection = this.getChunkAtBlock(x, y, z); - if (chunkSection != null) { - chunkSection.setLightAt(x & 15, y & 15, z & 15, light); - chunkSection.queueForRebuild(); - } - } - - getLightAt(x, y, z) { - let chunkSection = this.getChunkAtBlock(x, y, z); - return chunkSection == null ? 15 : chunkSection.getLightAt(x & 15, y & 15, z & 15); - } - - isHighestBlockAt(x, y, z) { - for (let i = y + 1; i < World.TOTAL_HEIGHT; i++) { - if (this.isSolidBlockAt(x, i, z)) { - return false; - } - } - return true; - } - - calculateLightAt(x, y, z) { - let maxBrightness = 0; - - // Get maximal brightness of surround blocks - let values = EnumBlockFace.values(); - for (let i in values) { - let face = values[i]; - - if (this.isTransparentBlockAt(x + face.x, y + face.y, z + face.z)) { - let brightness = this.getLightAt(x + face.x, y + face.y, z + face.z); - - maxBrightness = Math.max(maxBrightness, brightness); - } - } - - // Decrease maximum brightness by 6% - return Math.max(0, maxBrightness - 1); - } - onBlockChanged(x, y, z) { this.queueForRebuildInRegion(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1); } diff --git a/src/js/net/minecraft/client/world/block/Block.js b/src/js/net/minecraft/client/world/block/Block.js index c9bfd93..ad1665f 100644 --- a/src/js/net/minecraft/client/world/block/Block.js +++ b/src/js/net/minecraft/client/world/block/Block.js @@ -1,6 +1,6 @@ window.Block = class { - static blocks = []; + static blocks = new Map(); static create() { Block.STONE = new BlockStone(1, 0); @@ -19,7 +19,7 @@ window.Block = class { this.boundingBox = new BoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); // Register block - Block.blocks[id] = this; + Block.blocks.set(id, this); } getId() { @@ -39,6 +39,10 @@ window.Block = class { return typeId === 0 || Block.getById(typeId).isTransparent(); } + getLightValue() { + return 0; + } + isSolid() { return true; } @@ -167,7 +171,7 @@ window.Block = class { } static getById(typeId) { - return Block.blocks[typeId]; + return Block.blocks.get(typeId); } } \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/generator/WorldGenerator.js b/src/js/net/minecraft/client/world/generator/WorldGenerator.js index d0119fb..b495a7a 100644 --- a/src/js/net/minecraft/client/world/generator/WorldGenerator.js +++ b/src/js/net/minecraft/client/world/generator/WorldGenerator.js @@ -116,8 +116,8 @@ window.WorldGenerator = class { let perlin = this.forestNoise.perlin(absoluteX * 10, absoluteZ * 10); if (perlin > 0 && this.random.nextInt(2) === 0) { - // Get highest block at this position - let highestY = this.world.getHighestBlockYAt(absoluteX, absoluteZ); + // Get the highest block at this position + let highestY = this.world.getHeightAt(absoluteX, absoluteZ); // Don't place a tree if there is no grass if (this.world.getBlockAt(absoluteX, highestY, absoluteZ) === Block.GRASS.getId() diff --git a/src/js/net/minecraft/util/EnumSkyBlock.js b/src/js/net/minecraft/util/EnumSkyBlock.js new file mode 100644 index 0000000..d17fd00 --- /dev/null +++ b/src/js/net/minecraft/util/EnumSkyBlock.js @@ -0,0 +1,4 @@ +window.EnumSkyBlock = class { + static SKY = 0; + static BLOCK = 1; +} \ No newline at end of file diff --git a/src/js/net/minecraft/util/MetadataChunkBlock.js b/src/js/net/minecraft/util/MetadataChunkBlock.js new file mode 100644 index 0000000..eedfb99 --- /dev/null +++ b/src/js/net/minecraft/util/MetadataChunkBlock.js @@ -0,0 +1,162 @@ +window.MetadataChunkBlock = class { + + constructor(type, x1, y1, z1, x2, y2, z2) { + this.type = type; + this.x1 = x1; + this.y1 = y1; + this.z1 = z1; + this.x2 = x2; + this.y2 = y2; + this.z2 = z2; + } + + updateBlockLightning(world) { + for (let x = this.x1; x <= this.x2; x++) { + for (let z = this.z1; z <= this.z2; z++) { + for (let y = this.y1; y <= this.y2; y++) { + + let savedLightValue = world.getSavedLightValue(this.type, x, y, z); + + let level = 0; + let newLevel = 0; + + let typeId = world.getBlockAt(x, y, z); + let block = Block.getById(typeId); + + let opacity = typeId === 0 ? 0 : (block.getOpacity() * 255); + if (opacity === 0) { + opacity = 1; + } + + if (this.type === EnumSkyBlock.SKY) { + if (world.isHighestBlock(x, y, z)) { + level = 15; + } + } else if (this.type === EnumSkyBlock.BLOCK) { + level = typeId === 0 ? 0 : block.getLightValue(); + } + + if (opacity >= 15 && level === 0) { + newLevel = 0; + } else { + let x1Level = world.getSavedLightValue(this.type, x - 1, y, z); + let x2Level = world.getSavedLightValue(this.type, x + 1, y, z); + let bottomLevel = world.getSavedLightValue(this.type, x, y - 1, z); + let topLevel = world.getSavedLightValue(this.type, x, y + 1, z); + let z1Level = world.getSavedLightValue(this.type, x, y, z - 1); + let z2Level = world.getSavedLightValue(this.type, x, y, z + 1); + + newLevel = x1Level; + + if (x2Level > newLevel) { + newLevel = x2Level; + } + if (bottomLevel > newLevel) { + newLevel = bottomLevel; + } + if (topLevel > newLevel) { + newLevel = topLevel; + } + if (z1Level > newLevel) { + newLevel = z1Level; + } + if (z2Level > newLevel) { + newLevel = z2Level; + } + + newLevel -= opacity; + + if (newLevel < 0) { + newLevel = 0; + } + if (level > newLevel) { + newLevel = level; + } + } + + if (savedLightValue === newLevel) { + continue; + } + + world.setLightAt(this.type, x, y, z, newLevel); + + let decreasedLevel = newLevel - 1; + if (decreasedLevel < 0) { + decreasedLevel = 0; + } + + world.neighborLightPropagationChanged(this.type, x - 1, y, z, decreasedLevel); + world.neighborLightPropagationChanged(this.type, x, y - 1, z, decreasedLevel); + world.neighborLightPropagationChanged(this.type, x, y, z - 1, decreasedLevel); + + if (x + 1 >= this.x2) { + world.neighborLightPropagationChanged(this.type, x + 1, y, z, decreasedLevel); + } + if (y + 1 >= this.y2) { + world.neighborLightPropagationChanged(this.type, x, y + 1, z, decreasedLevel); + } + if (z + 1 >= this.z2) { + world.neighborLightPropagationChanged(this.type, x, y, z + 1, decreasedLevel); + } + } + } + } + } + + isOutsideOf(x1, y1, z1, x2, y2, z2) { + if (x1 >= this.x1 && y1 >= this.y1 && z1 >= this.z1 && x2 <= this.x2 && y2 <= this.y2 && z2 <= this.z2) { + return true; + } + + let radius = 1; + if (x1 >= this.x1 - radius + && y1 >= this.y1 - radius + && z1 >= this.z1 - radius + && x2 <= this.x2 + radius + && y2 <= this.y2 + radius + && z2 <= this.z2 + radius) { + + let distanceX = this.x2 - this.x1; + let distanceY = this.y2 - this.y1; + let distanceZ = this.z2 - this.z1; + + if (x1 > this.x1) { + x1 = this.x1; + } + if (y1 > this.y1) { + y1 = this.y1; + } + if (z1 > this.z1) { + z1 = this.z1; + } + if (x2 < this.x2) { + x2 = this.x2; + } + if (y2 < this.y2) { + y2 = this.y2; + } + if (z2 < this.z2) { + z2 = this.z2; + } + + let newDistanceX = x2 - x1; + let newDistanceY = y2 - y1; + let newDistanceZ = z2 - z1; + + let size = distanceX * distanceY * distanceZ; + let newSize = newDistanceX * newDistanceY * newDistanceZ; + + if (newSize - size <= 2) { + this.x1 = x1; + this.y1 = y1; + this.z1 = z1; + this.x2 = x2; + this.y2 = y2; + this.z2 = z2; + return true; + } + } + return false; + } + +} \ No newline at end of file diff --git a/src/start.js b/src/start.js index 009089d..a5ff9ca 100644 --- a/src/start.js +++ b/src/start.js @@ -51,6 +51,9 @@ loadScripts([ "src/js/net/minecraft/util/EnumBlockFace.js", "src/js/net/minecraft/util/Timer.js", "src/js/net/minecraft/util/Random.js", + "src/js/net/minecraft/util/EnumBlockFace.js", + "src/js/net/minecraft/util/EnumSkyBlock.js", + "src/js/net/minecraft/util/MetadataChunkBlock.js", "src/js/net/minecraft/util/Vector3.js", "src/js/net/minecraft/util/MovingObjectPosition.js", "src/js/net/minecraft/util/MathHelper.js",