From 0a16cb97210c467601b485267d7d19fa8cf3ffc7 Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Thu, 3 Feb 2022 01:18:22 +0100 Subject: [PATCH] improve mojang lightning --- src/js/net/minecraft/client/GameWindow.js | 2 +- src/js/net/minecraft/client/Minecraft.js | 4 + src/js/net/minecraft/client/entity/Player.js | 35 ++-- .../minecraft/client/render/BlockRenderer.js | 2 +- src/js/net/minecraft/client/world/Chunk.js | 155 +++++++++--------- src/js/net/minecraft/client/world/World.js | 75 +++++++-- .../client/world/block/BlockWater.js | 2 +- .../client/world/generator/WorldGenerator.js | 2 +- .../net/minecraft/util/MetadataChunkBlock.js | 2 +- 9 files changed, 167 insertions(+), 112 deletions(-) diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js index 92b2cd8..aaff7f4 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(1); + this.stats.showPanel(0); 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 a665c74..8fa9cca 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -27,6 +27,10 @@ window.Minecraft = class { } init() { + // Load spawn chunk + this.world.getChunkAt(0, 0); + this.player.respawn(); + // Start render loop this.running = true; this.requestNextFrame(); diff --git a/src/js/net/minecraft/client/entity/Player.js b/src/js/net/minecraft/client/entity/Player.js index 71a3c88..f397385 100644 --- a/src/js/net/minecraft/client/entity/Player.js +++ b/src/js/net/minecraft/client/entity/Player.js @@ -42,22 +42,33 @@ window.Player = class { this.prevFovModifier = 0; this.fovModifier = 0; this.timeFovChanged = 0; - - this.resetPos(); } - resetPos() { - this.setPos(0, 80, 0); + respawn() { + let spawnY = this.world.getHeightAt(0, 0); + this.setPosition(0, spawnY + 8, 0); } - setPos(x, y, z) { - this.x = x; - this.y = y; - this.z = z; + setPosition(x, y, z) { + let width = 0.3; + let height = 0.9; + this.boundingBox = new BoundingBox( + x - width, + y - height, + z - width, + x + width, + y + height, + z + width + ); - let w = 0.3; - let h = 0.9; - this.boundingBox = new BoundingBox(x - w, y - h, z - w, x + w, y + h, z + w); + this.motionX = 0; + this.motionY = 0; + this.motionZ = 0; + + // Update position + this.x = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0; + this.y = this.boundingBox.minY; + this.z = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0; } turn(motionX, motionY) { @@ -299,7 +310,7 @@ window.Player = class { let sneaking = false; if (Keyboard.isKeyDown("KeyR")) { // R - this.resetPos(); + this.respawn(); } if (Keyboard.isKeyDown("KeyW")) { // W moveForward++; diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index 35acc17..e80f656 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 = true; + static CLASSIC_LIGHTNING = false; constructor(worldRenderer) { this.worldRenderer = worldRenderer; diff --git a/src/js/net/minecraft/client/world/Chunk.js b/src/js/net/minecraft/client/world/Chunk.js index 59aa3de..9e78950 100644 --- a/src/js/net/minecraft/client/world/Chunk.js +++ b/src/js/net/minecraft/client/world/Chunk.js @@ -26,27 +26,22 @@ window.Chunk = class { } generateSkylightMap() { - let highest = World.TOTAL_HEIGHT; + // Calculate height map for (let x = 0; x < 16; x++) { for (let z = 0; z < 16; z++) { - this.heightMap[z << 4 | x] = -1; - + this.setHeightAt(x, z, 0); // TODO set to 0 to calculate proper lightning this.updateHeightMap(x, World.TOTAL_HEIGHT, z); - - if ((this.heightMap[z << 4 | x] & 0xff) < highest) { - highest = this.heightMap[z << 4 | x] & 0xff; - } } } - this.highestY = highest; - for (let k = 0; k < 16; k++) { - for (let i1 = 0; i1 < 16; i1++) { - this.notifyNeighbors(k, i1); + // Update light of neighbor blocks + for (let x = 0; x < 16; x++) { + for (let z = 0; z < 16; z++) { + this.notifyNeighbors(x, z); } - } + // Rebuild all sections this.setModifiedAllSections(); } @@ -76,57 +71,34 @@ window.Chunk = class { } updateHeightMap(relX, y, relZ) { - let currentHighestY = this.heightMap[relZ << 4 | relX] & 0xff; + let currentHighestY = this.getHeightAt(relX, relZ); let highestY = currentHighestY; if (y > currentHighestY) { highestY = y; } - while (highestY > 0) { - let typeId = this.getBlockAt(relX, highestY, relZ); - let block = Block.getById(typeId); - if (typeId !== 0 && block.getOpacity() !== 0) { - break; - } + highestY = this.calculateHeightAt(relX, relZ, highestY); - highestY--; - } if (highestY === currentHighestY) { return; } - //this.world.heightLevelChanged(relX, relZ, highestY, currentHighestY); - this.heightMap[relZ << 4 | relX] = highestY; - if (highestY < this.highestY) { - this.highestY = highestY; - } else { - let highest = 127; - for (let cx = 0; cx < 16; cx++) { - for (let cz = 0; cz < 16; cz++) { - if ((this.heightMap[cz << 4 | cx] & 0xff) < highest) { - highest = this.heightMap[cz << 4 | cx] & 0xff; - } - } - } - - this.highestY = highest; - } + this.setHeightAt(relX, relZ, highestY); let x = this.x * 16 + relX; let z = this.z * 16 + relZ; if (highestY < currentHighestY) { - for (let l2 = highestY; l2 < currentHighestY; l2++) { - this.setLightAt(EnumSkyBlock.SKY, relX, l2, relZ, 15); + for (let hy = highestY; hy < currentHighestY; hy++) { + this.setLightAt(EnumSkyBlock.SKY, relX, hy, relZ, 15); } - } else { this.world.updateLight(EnumSkyBlock.SKY, x, currentHighestY, z, x, highestY, z); for (let hy = currentHighestY; hy < highestY; hy++) { this.setLightAt(EnumSkyBlock.SKY, relX, hy, relZ, 0); } - } + let lightLevel = 15; let prevHeight = highestY; while (highestY > 0 && lightLevel > 0) { @@ -147,15 +119,7 @@ window.Chunk = class { this.setLightAt(EnumSkyBlock.SKY, relX, highestY, relZ, lightLevel); } - while (highestY > 0) { - let typeId = this.getBlockID(relX, highestY - 1, relZ); - let block = Block.getById(typeId); - - if (typeId !== 0 && block.isSolid()) { - break; - } - highestY--; - } + highestY = this.calculateHeightAt(relX, relZ, highestY); if (highestY !== prevHeight) { this.world.updateLight(EnumSkyBlock.SKY, x - 1, highestY, z - 1, x + 1, prevHeight, z + 1); @@ -163,34 +127,76 @@ window.Chunk = class { this.setModifiedAllSections(); } + calculateHeightAt(x, z, startY) { + let y = startY; + while (y > 0) { + let typeId = this.getBlockAt(x, y - 1, z); + let block = Block.getById(typeId); + let opacity = typeId === 0 ? 0 : block.getOpacity(); + + if (opacity !== 0) { + break; + } + y--; + } + return y; + } + + updateHeightMapAt(x, z) { + let y = this.calculateHeightAt(x, z, World.TOTAL_HEIGHT); + this.setHeightAt(x, z, y); + } + + setHeightAt(x, z, height) { + this.heightMap[z << 4 | x] = height; + } + + /** + * Is the highest solid block or above + */ + isHighestBlock(x, y, z) { + return y >= this.getHighestBlockAt(x, z); + } + + /** + * Is above the highest solid block + */ + isAboveGround(x, y, z) { + return y >= this.getHeightAt(x, z); + } + + /** + * Get the first non-solid block + */ + getHeightAt(x, z) { + return this.heightMap[z << 4 | x]; + } + + /** + * Get the highest solid block + */ + getHighestBlockAt(x, z) { + return this.getHeightAt(x, z) - 1; + } + setLightAt(sourceType, x, y, z, level) { - this.getSection(y >> 4).setLightAt(sourceType, x, y & 15, z, level); + let section = this.getSection(y >> 4); + section.setLightAt(sourceType, x, y & 15, z, level); } setBlockAt(x, y, z, typeId) { - let byte0 = typeId; - let height = this.heightMap[z << 4 | x] & 0xff; - + let height = this.getHeightAt(x, z); let prevTypeId = this.getBlockAt(x, y, z); if (prevTypeId === typeId) { return false; } - let totalX = this.x * 16 + x; - let totalZ = this.z * 16 + z; - - this.getSection(y >> 4).setBlockAt(x, y & 15, z, byte0); + this.getSection(y >> 4).setBlockAt(x, y & 15, z, typeId); if (!this.loaded) { return; } - //if (k1 !== 0 && !this.worldObj.multiplayerWorld) { - //Block.blocksList[k1].onBlockRemoval(this.world, l1, j, i2); - //} - //this.data.setNibble(i, j, k, i1); - //if (!this.worldObj.worldProvider.field_6478_e) { - let block = Block.getById(typeId); if (typeId !== 0 && block.isSolid()) { if (y >= height) { @@ -200,18 +206,13 @@ window.Chunk = class { this.updateHeightMap(x, y, z); } + let totalX = this.x * 16 + x; + let totalZ = this.z * 16 + z; + this.world.updateLight(EnumSkyBlock.SKY, totalX, y, totalZ, totalX, y, totalZ); - //} - this.world.updateLight(EnumSkyBlock.BLOCK, totalX, y, totalZ, totalX, y, totalZ); + this.notifyNeighbors(x, z); - - if (typeId !== 0) { - //Block.blocksList[l].onBlockAdded(this.worldObj, l1, j, i2); - } - - //this.data.setNibble(i, j, k, i1); - this.setModifiedAllSections(); return true; } @@ -224,14 +225,6 @@ window.Chunk = class { 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; - } - getSection(y) { return this.sections[y]; } diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index af8efe6..7d8b3cf 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -1,18 +1,18 @@ window.World = class { - static TOTAL_HEIGHT = ChunkSection.SIZE * 16 - 1; + static TOTAL_HEIGHT = ChunkSection.SIZE * 8 - 1; // ChunkSection.SIZE * 16 - 1; constructor(minecraft) { this.minecrat = minecraft; this.group = new THREE.Object3D(); this.group.matrixAutoUpdate = false; + this.chunks = new Map(); + this.lightUpdateQueue = []; // Load world this.generator = new WorldGenerator(this, Date.now() % 100000); - - this.lightUpdateQueue = []; } onTick() { @@ -81,14 +81,35 @@ window.World = class { } updateLights() { - // Update lights in queue - let i = 5000; - while (this.lightUpdateQueue.length > 0) { - if (i <= 0) { - return true; + let scope = this; + + if (this.lightUpdateQueue.length > 10) { + // Update lights async + setTimeout(function () { + // Update lights in queue + let i = 5000; + while (scope.lightUpdateQueue.length > 0) { + if (i <= 0) { + break; + } + + let meta = scope.lightUpdateQueue.shift(); + meta.updateBlockLightning(scope); + i--; + } + }, 0); + } else { + // Update lights in queue + let i = 10; + while (scope.lightUpdateQueue.length > 0) { + if (i <= 0) { + return true; + } + + let meta = scope.lightUpdateQueue.shift(); + meta.updateBlockLightning(scope); + i--; } - this.lightUpdateQueue.shift().updateBlockLightning(this); - i--; } return false; } @@ -116,8 +137,11 @@ window.World = class { } } + // Add light update region to queue this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2)); - if (this.lightUpdateQueue.length > 0x186a0) { + + // Max light updates in queue + if (this.lightUpdateQueue.length > 100000) { this.lightUpdateQueue = []; } } @@ -141,7 +165,7 @@ window.World = class { return; } if (sourceType === EnumSkyBlock.SKY) { - if (this.isHighestBlock(x, y, z)) { + if (this.isAboveGround(x, y, z)) { level = 15; } } else if (sourceType === EnumSkyBlock.BLOCK) { @@ -155,17 +179,40 @@ window.World = class { } } + /** + * Get the first non-solid block + */ getHeightAt(x, z) { if (!this.chunkExists(x >> 4, z >> 4)) { return 0; } - return this.getChunkAt(x >> 4, z >> 4).getHeightAt(x & 15, z & 15); } + /** + * Get the highest solid block + */ + getHighestBlockAt(x, z) { + if (!this.chunkExists(x >> 4, z >> 4)) { + return 0; + } + return this.getChunkAt(x >> 4, z >> 4).getHighestBlockAt(x & 15, z & 15); + } + + /** + * Is the highest solid block or above + */ isHighestBlock(x, y, z) { let chunk = this.getChunkAt(x >> 4, z >> 4) - return y >= chunk.getHeightAt(x & 15, z & 15); + return chunk.isHighestBlock(x & 15, y, z & 15); + } + + /** + * Is above the highest solid block + */ + isAboveGround(x, y, z) { + let chunk = this.getChunkAt(x >> 4, z >> 4) + return chunk.isAboveGround(x & 15, y, z & 15); } getTotalLightAt(x, y, z) { diff --git a/src/js/net/minecraft/client/world/block/BlockWater.js b/src/js/net/minecraft/client/world/block/BlockWater.js index b50cd86..dc504dd 100644 --- a/src/js/net/minecraft/client/world/block/BlockWater.js +++ b/src/js/net/minecraft/client/world/block/BlockWater.js @@ -5,7 +5,7 @@ window.BlockWater = class extends Block { } getOpacity() { - return 0.93; + return 0.01; } isSolid() { diff --git a/src/js/net/minecraft/client/world/generator/WorldGenerator.js b/src/js/net/minecraft/client/world/generator/WorldGenerator.js index bcb9548..1fe3429 100644 --- a/src/js/net/minecraft/client/world/generator/WorldGenerator.js +++ b/src/js/net/minecraft/client/world/generator/WorldGenerator.js @@ -117,7 +117,7 @@ window.WorldGenerator = class { if (perlin > 0 && this.random.nextInt(2) === 0) { // Get the highest block at this position - let highestY = this.world.getHeightAt(absoluteX, absoluteZ); + let highestY = this.world.getHighestBlockAt(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/MetadataChunkBlock.js b/src/js/net/minecraft/util/MetadataChunkBlock.js index 38caeb9..0205b1b 100644 --- a/src/js/net/minecraft/util/MetadataChunkBlock.js +++ b/src/js/net/minecraft/util/MetadataChunkBlock.js @@ -42,7 +42,7 @@ window.MetadataChunkBlock = class { let level = 0; if (this.type === EnumSkyBlock.SKY) { - if (world.isHighestBlock(x, y, z)) { + if (world.isAboveGround(x, y, z)) { level = 15; } } else if (this.type === EnumSkyBlock.BLOCK) {