From 7858e98ffa1fe2bc317b2de681fce90dea0fc4b1 Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Sun, 13 Feb 2022 02:54:57 +0100 Subject: [PATCH] implement torch block and block lightning --- .../minecraft/client/inventory/Inventory.js | 9 + .../minecraft/client/render/BlockRenderer.js | 166 ++++++++++++++---- .../minecraft/client/render/Tessellator.js | 2 +- .../minecraft/client/render/WorldRenderer.js | 31 +++- src/js/net/minecraft/client/world/Chunk.js | 54 ++++++ .../minecraft/client/world/ChunkSection.js | 2 +- src/js/net/minecraft/client/world/World.js | 35 +++- .../net/minecraft/client/world/block/Block.js | 11 +- .../client/world/block/BlockTorch.js | 20 +++ .../client/world/block/BlockWater.js | 2 +- src/js/net/minecraft/util/BlockRenderType.js | 4 + .../net/minecraft/util/MetadataChunkBlock.js | 2 +- src/resources/terrain/terrain.png | Bin 7547 -> 6764 bytes src/start.js | 2 + 14 files changed, 293 insertions(+), 47 deletions(-) create mode 100644 src/js/net/minecraft/client/world/block/BlockTorch.js create mode 100644 src/js/net/minecraft/util/BlockRenderType.js diff --git a/src/js/net/minecraft/client/inventory/Inventory.js b/src/js/net/minecraft/client/inventory/Inventory.js index 55c5309..0693259 100644 --- a/src/js/net/minecraft/client/inventory/Inventory.js +++ b/src/js/net/minecraft/client/inventory/Inventory.js @@ -3,6 +3,15 @@ window.Inventory = class { constructor() { this.selectedSlotIndex = 0; this.items = []; + + // Default items in inventory + this.items[0] = 1; + this.items[1] = 2; + this.items[2] = 3; + this.items[3] = 17; + this.items[4] = 18; + this.items[5] = 12; + this.items[6] = 50; } setItemInSelectedSlot(typeId) { diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index 16ba948..1825c34 100644 --- a/src/js/net/minecraft/client/render/BlockRenderer.js +++ b/src/js/net/minecraft/client/render/BlockRenderer.js @@ -9,6 +9,17 @@ window.BlockRenderer = class { } renderBlock(world, block, x, y, z) { + switch (block.getRenderType()) { + case BlockRenderType.BLOCK: + this.renderSolidBlock(world, block, x, y, z); + break; + case BlockRenderType.TORCH: + this.renderTorch(world, block, x, y, z); + break; + } + } + + renderSolidBlock(world, block, x, y, z) { let boundingBox = block.getBoundingBox(world, x, y, z); // Render all faces @@ -17,7 +28,7 @@ window.BlockRenderer = class { let face = values[i]; // Check if face is hidden by other block - if (block.shouldRenderFace(world, x, y, z, face)) { + if (world === null || block.shouldRenderFace(world, x, y, z, face)) { // Render face this.renderFace(world, block, boundingBox, face, x, y, z); @@ -53,41 +64,46 @@ window.BlockRenderer = class { this.tessellator.setColor(color, color, color); } + // Add face to tessellator + this.addFace(world, face, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + } + + addFace(world, face, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV) { if (face === EnumBlockFace.BOTTOM) { - this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV); - this.addBlockCorner(world, face, minX, minY, minZ, minU, minV); - this.addBlockCorner(world, face, maxX, minY, minZ, maxU, minV); this.addBlockCorner(world, face, maxX, minY, maxZ, maxU, maxV); + this.addBlockCorner(world, face, maxX, minY, minZ, maxU, minV); + this.addBlockCorner(world, face, minX, minY, minZ, minU, minV); + this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV); } if (face === EnumBlockFace.TOP) { - this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, maxV); - this.addBlockCorner(world, face, maxX, maxY, minZ, maxU, minV); - this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV); this.addBlockCorner(world, face, minX, maxY, maxZ, minU, maxV); + this.addBlockCorner(world, face, minX, maxY, minZ, minU, minV); + this.addBlockCorner(world, face, maxX, maxY, minZ, maxU, minV); + this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, maxV); } 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.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.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.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); + } + if (face === EnumBlockFace.SOUTH) { + this.addBlockCorner(world, face, minX, maxY, maxZ, maxU, minV); this.addBlockCorner(world, face, maxX, maxY, maxZ, minU, minV); + this.addBlockCorner(world, face, maxX, minY, maxZ, minU, maxV); + this.addBlockCorner(world, face, minX, minY, maxZ, maxU, maxV); + } + if (face === EnumBlockFace.WEST) { + this.addBlockCorner(world, face, minX, minY, maxZ, minU, maxV); + this.addBlockCorner(world, face, minX, minY, minZ, maxU, maxV); + this.addBlockCorner(world, face, minX, maxY, minZ, maxU, minV); + this.addBlockCorner(world, face, minX, maxY, maxZ, minU, minV); + } + if (face === EnumBlockFace.EAST) { + this.addBlockCorner(world, face, maxX, maxY, maxZ, maxU, minV); + this.addBlockCorner(world, face, maxX, maxY, minZ, minU, minV); + this.addBlockCorner(world, face, maxX, minY, minZ, minU, maxV); + this.addBlockCorner(world, face, maxX, minY, maxZ, maxU, maxV); } } @@ -127,7 +143,7 @@ window.BlockRenderer = class { let typeId = world.getBlockAt(x + offsetX, y + offsetY, z + offsetZ); // Does it contain air? - if (typeId === 0 || Block.getById(typeId).isTransparent()) { + if (typeId === 0 || !Block.getById(typeId).isSolid()) { // Sum up the light levels totalLightLevel += world.getTotalLightAt(x + offsetX, y + offsetY, z + offsetZ); @@ -141,25 +157,111 @@ window.BlockRenderer = class { return totalBlocks === 0 ? 0 : totalLightLevel / totalBlocks; } + renderTorch(world, block, x, y, z) { + let boundingBox = block.getBoundingBox(world, x, y, z); + + // Thickness of the torch + let size = 1 / 16; + + // Vertex mappings + let minX = x + 0.5 - size; + let minY = y; + let minZ = z + 0.5 - size; + let maxX = x + 0.5 + size; + let maxY = y + 10 / 16; + let maxZ = z + 0.5 + size; + + // UV Mapping + let textureIndex = block.getTextureForFace(EnumBlockFace.NORTH); + let minU = (textureIndex % 16) / 16.0; + let minV = Math.floor(textureIndex / 16) / 16.0; + + // Cut to torch texture at 7:6 + minU += 7 / 256; + minV += 6 / 256; + + // Size of torch texture (2x10) + let maxU = minU + 2 / 256; + let maxV = minV + 10 / 256; + + // Flip V + minV = 1 - minV; + maxV = 1 - maxV; + + // Set color with shading + this.tessellator.setColor(1, 1, 1); + + // Add faceS to tessellator + this.addFace(world, EnumBlockFace.NORTH, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + this.addFace(world, EnumBlockFace.EAST, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + this.addFace(world, EnumBlockFace.SOUTH, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + this.addFace(world, EnumBlockFace.WEST, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + this.addFace(world, EnumBlockFace.TOP, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV + 8 / 256); + } + + renderGuiItem(block) { + // Vertex mappings + let minX = 0; + let minY = 0; + let minZ = 0; + let maxX = 1; + let maxY = 1; + let maxZ = 1; + + // UV Mapping + let textureIndex = block.getTextureForFace(EnumBlockFace.NORTH); + let minU = (textureIndex % 16) / 16.0; + let maxU = minU + (16 / 256); + let minV = Math.floor(textureIndex / 16) / 16.0; + let maxV = minV + (16 / 256); + + // Flip V + minV = 1 - minV; + maxV = 1 - maxV; + + // Render item + this.addFace(null, EnumBlockFace.NORTH, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV); + } + renderGuiBlock(group, block, x, y, size) { this.tessellator.startDrawing(); let boundingBox = block.getBoundingBox(null, 0, 0, 0); - this.renderFace(null, block, boundingBox, EnumBlockFace.TOP, 0, 0, 0); - this.renderFace(null, block, boundingBox, EnumBlockFace.NORTH, 0, 0, 0); - this.renderFace(null, block, boundingBox, EnumBlockFace.EAST, 0, 0, 0); + // Render block by type + switch (block.getRenderType()) { + case BlockRenderType.BLOCK: + this.renderFace(null, block, boundingBox, EnumBlockFace.TOP, 0, 0, 0); + this.renderFace(null, block, boundingBox, EnumBlockFace.NORTH, 0, 0, 0); + this.renderFace(null, block, boundingBox, EnumBlockFace.EAST, 0, 0, 0); + break; + default: + this.renderGuiItem(block); + break; + } + + // Create mesh let mesh = this.tessellator.draw(group); mesh.geometry.center(); - mesh.rotation.x = -MathHelper.toRadians(45 / 1.5); - mesh.rotation.y = MathHelper.toRadians(45); + // Rotate block + switch (block.getRenderType()) { + case BlockRenderType.BLOCK: + mesh.rotation.x = MathHelper.toRadians(45 / 1.5); + mesh.rotation.y = -MathHelper.toRadians(45 + 90); + break; + default: + mesh.rotation.y = MathHelper.toRadians(180); + size += 5; + break; + } + // Relative position mesh.position.x = x; mesh.position.y = -y; - mesh.position.z = -3; + mesh.position.z = -10; - //let scale = Math.cos(Date.now() / 1000) * 100; + // Scale mesh.scale.x = size; mesh.scale.y = size; mesh.scale.z = size; diff --git a/src/js/net/minecraft/client/render/Tessellator.js b/src/js/net/minecraft/client/render/Tessellator.js index 758cbe3..b3d8a2e 100644 --- a/src/js/net/minecraft/client/render/Tessellator.js +++ b/src/js/net/minecraft/client/render/Tessellator.js @@ -3,7 +3,7 @@ window.Tessellator = class { constructor() { this.material = new THREE.MeshBasicMaterial({ vertexColors: THREE.VertexColors, - side: THREE.BackSide, + side: THREE.FrontSide, transparent: true, depthTest: true }); diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js index 91c77a5..1ffe78e 100644 --- a/src/js/net/minecraft/client/render/WorldRenderer.js +++ b/src/js/net/minecraft/client/render/WorldRenderer.js @@ -17,6 +17,11 @@ window.WorldRenderer = class { this.textureSun.magFilter = THREE.NearestFilter; this.textureSun.minFilter = THREE.NearestFilter; + // Load moon texture + this.textureMoon = new THREE.TextureLoader().load('src/resources/terrain/moon.png'); + this.textureMoon.magFilter = THREE.NearestFilter; + this.textureMoon.minFilter = THREE.NearestFilter; + // Block Renderer this.blockRenderer = new BlockRenderer(this); @@ -181,6 +186,13 @@ window.WorldRenderer = class { } } + rebuildAll() { + let world = this.minecraft.world; + for (let [index, chunk] of world.chunks) { + chunk.setModifiedAllSections(); + } + } + generateSky() { // Create sky group this.skyGroup = new THREE.Scene(); @@ -188,19 +200,32 @@ window.WorldRenderer = class { // Create sun let geometry = new THREE.PlaneGeometry(1, 1); - let material = new THREE.MeshBasicMaterial({ - color: 0xffff00, + let materialSun = new THREE.MeshBasicMaterial({ side: THREE.FrontSide, map: this.textureSun, alphaMap: this.textureSun, blending: THREE.AdditiveBlending, transparent: true }); - this.sun = new THREE.Mesh(geometry, material); + this.sun = new THREE.Mesh(geometry, materialSun); this.sun.translateZ(-2); this.sun.renderOrder = 999; this.sun.material.depthTest = false; this.skyGroup.add(this.sun); + + // Create moon + let materialMoon = new THREE.MeshBasicMaterial({ + side: THREE.BackSide, + map: this.textureMoon, + alphaMap: this.textureMoon, + blending: THREE.AdditiveBlending, + transparent: true + }); + this.moon = new THREE.Mesh(geometry, materialMoon); + this.moon.translateZ(2); + this.moon.renderOrder = 999; + this.moon.material.depthTest = false; + this.skyGroup.add(this.moon); } renderSky(partialTicks) { diff --git a/src/js/net/minecraft/client/world/Chunk.js b/src/js/net/minecraft/client/world/Chunk.js index 9e78950..98724e7 100644 --- a/src/js/net/minecraft/client/world/Chunk.js +++ b/src/js/net/minecraft/client/world/Chunk.js @@ -45,6 +45,60 @@ window.Chunk = class { this.setModifiedAllSections(); } + generateBlockLightMap() { + let targetY = 32; + for (let x = 0; x < 16; x++) { + for (let z = 0; z < 16; z++) { + for (let y = 0; y < World.TOTAL_HEIGHT; y++) { + let section = this.getSection(y >> 4); + + let typeId = section.getBlockAt(x, y & 15, z); + let block = Block.getById(typeId); + let blockLight = typeId === 0 ? 0 : block.getLightValue(); + + if (blockLight > 0) { + section.setLightAt(EnumSkyBlock.BLOCK, x, y & 15, z, blockLight); + } + } + + let level = 15; + for (let y = targetY - 2; y < 128 && level > 0;) { + y++; + + let section = this.getSection(y >> 4); + + let typeId = section.getBlockAt(x, y & 15, z); + let block = Block.getById(typeId); + + let opacity = block.getOpacity(); + let blockLight = typeId === 0 ? 0 : block.getLightValue(); + + if (opacity === 0) { + opacity = 1; + } + + level -= opacity; + + if (blockLight > level) { + level = blockLight; + } + + if (level < 0) { + level = 0; + } + + section.setLightAt(EnumSkyBlock.BLOCK, x, y & 15, z, blockLight); + } + } + } + + this.world.updateLight(EnumSkyBlock.Block, + this.x * 16, targetY - 1, this.z * 16, + this.x * 16 + 16, targetY + 1, this.z * 16 + 16 + ); + this.setModifiedAllSections(); + } + updateBlockLight() { this.setModifiedAllSections(); } diff --git a/src/js/net/minecraft/client/world/ChunkSection.js b/src/js/net/minecraft/client/world/ChunkSection.js index 427aec3..0e6055c 100644 --- a/src/js/net/minecraft/client/world/ChunkSection.js +++ b/src/js/net/minecraft/client/world/ChunkSection.js @@ -99,7 +99,7 @@ window.ChunkSection = class { getTotalLightAt(x, y, z) { let index = y << 8 | z << 4 | x; - let skyLight = this.skyLight[index]; + let skyLight = this.skyLight[index] - this.world.skylightSubtracted; let blockLight = this.blockLight[index]; if (blockLight > skyLight) { skyLight = blockLight; diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index b3fae4c..9681ae3 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -39,6 +39,15 @@ window.World = class { return distance2 - distance1; }); + // Update skylight subtracted (To make the night dark) + let lightLevel = this.calculateSkylightSubtracted(1.0); + if (lightLevel !== this.skylightSubtracted) { + this.skylightSubtracted = lightLevel; + + // Rebuild all chunks + this.minecraft.worldRenderer.rebuildAll(); + } + // Update world time this.time++; } @@ -54,6 +63,7 @@ window.World = class { // Init chunk.generateSkylightMap(); + chunk.generateBlockLightMap(); // Register chunk.loaded = true; @@ -171,9 +181,12 @@ window.World = class { level = 15; } } else if (sourceType === EnumSkyBlock.BLOCK) { - let i1 = this.getBlockAt(x, y, z); - if (0 > level) { // TODO - level = 0; + let typeId = this.getBlockAt(x, y, z); + let block = Block.getById(typeId); + let blockLight = typeId === 0 ? 0 : block.getLightValue(); + + if (blockLight > level) { + level = blockLight; } } if (this.getSavedLightValue(sourceType, x, y, z) !== level) { @@ -318,7 +331,7 @@ window.World = class { let blockId = this.getBlockAt(x, y, z); let block = Block.getById(blockId); - if (block != null && block.canCollide()) { + if (block != null && block.canInteract()) { let hit = block.collisionRayTrace(x, y, z, from, to); if (hit != null) { return hit; @@ -412,7 +425,7 @@ window.World = class { let blockId = this.getBlockAt(x, y, z); let block = Block.getById(blockId); - if (block != null && block.canCollide()) { + if (block != null && block.canInteract()) { let hit = block.collisionRayTrace(x, y, z, from, to); if (hit != null) { return hit; @@ -466,4 +479,16 @@ window.World = class { } return MathHelper.hsbToRgb(0.6222222 - temperature * 0.05, 0.5 + temperature * 0.1, 1.0); } + + calculateSkylightSubtracted(partialTicks) { + let angle = this.getCelestialAngle(partialTicks); + let level = 1.0 - (Math.cos(angle * 3.141593 * 2.0) * 2.0 + 0.5); + if (level < 0.0) { + level = 0.0; + } + if (level > 1.0) { + level = 1.0; + } + return Math.floor(level * 11); + } } \ 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 8388fd0..4a67817 100644 --- a/src/js/net/minecraft/client/world/block/Block.js +++ b/src/js/net/minecraft/client/world/block/Block.js @@ -1,7 +1,7 @@ window.Block = class { static blocks = new Map(); - + static create() { Block.STONE = new BlockStone(1, 0); Block.GRASS = new BlockGrass(2, 1); @@ -10,6 +10,7 @@ window.Block = class { Block.LEAVE = new BlockLeave(18, 6); Block.WATER = new BlockWater(9, 7); Block.SAND = new BlockSand(12, 8) + Block.TORCH = new BlockTorch(50, 9) } constructor(id, textureSlotId = id) { @@ -26,6 +27,10 @@ window.Block = class { return this.id; } + getRenderType() { + return BlockRenderType.BLOCK; + } + getTextureForFace(face) { return this.textureSlotId; } @@ -36,7 +41,7 @@ window.Block = class { shouldRenderFace(world, x, y, z, face) { let typeId = world.getBlockAtFace(x, y, z, face); - return typeId === 0 || Block.getById(typeId).isTransparent(); + return typeId === 0 || !Block.getById(typeId).isSolid(); } getLightValue() { @@ -51,7 +56,7 @@ window.Block = class { return 1.0; } - canCollide() { + canInteract() { return true; } diff --git a/src/js/net/minecraft/client/world/block/BlockTorch.js b/src/js/net/minecraft/client/world/block/BlockTorch.js new file mode 100644 index 0000000..da013ea --- /dev/null +++ b/src/js/net/minecraft/client/world/block/BlockTorch.js @@ -0,0 +1,20 @@ +window.BlockTorch = class extends Block { + + constructor(id, textureSlotId) { + super(id, textureSlotId); + + this.boundingBox = new BoundingBox(0.4, 0.0, 0.4, 0.6, 0.6, 0.6); + } + + getLightValue() { + return 14; + } + + isSolid() { + return false; + } + + getRenderType() { + return BlockRenderType.TORCH; + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/block/BlockWater.js b/src/js/net/minecraft/client/world/block/BlockWater.js index dc504dd..6755cb7 100644 --- a/src/js/net/minecraft/client/world/block/BlockWater.js +++ b/src/js/net/minecraft/client/world/block/BlockWater.js @@ -12,7 +12,7 @@ window.BlockWater = class extends Block { return false; } - canCollide() { + canInteract() { return false; } diff --git a/src/js/net/minecraft/util/BlockRenderType.js b/src/js/net/minecraft/util/BlockRenderType.js new file mode 100644 index 0000000..f902edf --- /dev/null +++ b/src/js/net/minecraft/util/BlockRenderType.js @@ -0,0 +1,4 @@ +window.BlockRenderType = class { + static BLOCK = 0; + static TORCH = 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 index 0205b1b..a52af31 100644 --- a/src/js/net/minecraft/util/MetadataChunkBlock.js +++ b/src/js/net/minecraft/util/MetadataChunkBlock.js @@ -46,7 +46,7 @@ window.MetadataChunkBlock = class { level = 15; } } else if (this.type === EnumSkyBlock.BLOCK) { - level = 0; // TODO + level = typeId === 0 ? 0 : block.getLightValue(); } if (opacity >= 15 && level === 0) { diff --git a/src/resources/terrain/terrain.png b/src/resources/terrain/terrain.png index 20e058ba5106219d0a4c92fbb6fcb301b46c07b4..23f3947d0d3d560475e7959696619f6105ec3372 100644 GIT binary patch literal 6764 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 literal 7547 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 Ks#m6CAM+n}9q>5- diff --git a/src/start.js b/src/start.js index 2f9cd86..38af26a 100644 --- a/src/start.js +++ b/src/start.js @@ -96,6 +96,7 @@ loadTexture([ "src/js/net/minecraft/util/MathHelper.js", "src/js/net/minecraft/util/BoundingBox.js", "src/js/net/minecraft/util/Keyboard.js", + "src/js/net/minecraft/util/BlockRenderType.js", "src/js/net/minecraft/client/gui/Gui.js", "src/js/net/minecraft/client/gui/GuiScreen.js", "src/js/net/minecraft/client/gui/widgets/GuiButton.js", @@ -113,6 +114,7 @@ loadTexture([ "src/js/net/minecraft/client/world/block/BlockLeave.js", "src/js/net/minecraft/client/world/block/BlockWater.js", "src/js/net/minecraft/client/world/block/BlockSand.js", + "src/js/net/minecraft/client/world/block/BlockTorch.js", "src/js/net/minecraft/client/world/ChunkSection.js", "src/js/net/minecraft/client/world/Chunk.js", "src/js/net/minecraft/client/world/World.js",