diff --git a/src/js/net/minecraft/client/GameSettings.js b/src/js/net/minecraft/client/GameSettings.js index 6b0edb0..c56a963 100644 --- a/src/js/net/minecraft/client/GameSettings.js +++ b/src/js/net/minecraft/client/GameSettings.js @@ -9,6 +9,7 @@ export default class GameSettings { this.viewBobbing = true; this.ambientOcclusion = true; this.sensitivity = 100; + this.viewDistance = 4; } load() { diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index c8772ee..be81312 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -18,7 +18,7 @@ import * as THREE from "../../../../../libraries/three.module.js"; export default class Minecraft { - static VERSION = "1.0.0" + static VERSION = "1.0.1" static URL_GITHUB = "https://github.com/labystudio/js-minecraft"; /** @@ -88,6 +88,7 @@ export default class Minecraft { this.worldRenderer.reset(); this.itemRenderer.reset(); + this.world.chunks.clear(); this.world = null; this.player = null; this.loadingScreen = null; @@ -232,7 +233,7 @@ export default class Minecraft { let cameraChunkX = Math.floor(this.player.x) >> 4; let cameraChunkZ = Math.floor(this.player.z) >> 4; - let renderDistance = WorldRenderer.RENDER_DISTANCE; + let renderDistance = this.settings.viewDistance; let requiredChunks = Math.pow(renderDistance * 2 - 1, 2); let loadedChunks = this.world.chunks.size; @@ -354,6 +355,9 @@ export default class Minecraft { } } } + + // Rebuild multiple chunk sections + this.worldRenderer.flushRebuild = true; } } diff --git a/src/js/net/minecraft/client/gui/GuiScreen.js b/src/js/net/minecraft/client/gui/GuiScreen.js index 46caf72..b31a157 100644 --- a/src/js/net/minecraft/client/gui/GuiScreen.js +++ b/src/js/net/minecraft/client/gui/GuiScreen.js @@ -6,6 +6,7 @@ export default class GuiScreen extends Gui { super(); this.buttonList = []; + this.previousScreen = null; } setup(minecraft, width, height) { @@ -43,7 +44,7 @@ export default class GuiScreen extends Gui { keyTyped(key, character) { if (key === "Escape") { - this.minecraft.displayScreen(null); + this.minecraft.displayScreen(this.previousScreen); return true; } diff --git a/src/js/net/minecraft/client/gui/screens/GuiControls.js b/src/js/net/minecraft/client/gui/screens/GuiControls.js index 53025b2..9c73be3 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiControls.js +++ b/src/js/net/minecraft/client/gui/screens/GuiControls.js @@ -35,7 +35,7 @@ export default class GuiControls extends GuiScreen { settings.togglePerspective = key; })); - this.buttonList.push(new GuiButton("Done", this.width / 2 - 100, y + 110, 200, 20, () => { + this.buttonList.push(new GuiButton("Done", this.width / 2 - 100, y + 130, 200, 20, () => { this.minecraft.displayScreen(this.previousScreen); })); } diff --git a/src/js/net/minecraft/client/gui/screens/GuiCreateWorld.js b/src/js/net/minecraft/client/gui/screens/GuiCreateWorld.js index 0009dc7..a0a8252 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiCreateWorld.js +++ b/src/js/net/minecraft/client/gui/screens/GuiCreateWorld.js @@ -3,6 +3,7 @@ import GuiButton from "../widgets/GuiButton.js"; import World from "../../world/World.js"; import GuiTextField from "../widgets/GuiTextField.js"; import Random from "../../../util/Random.js"; +import Long from "../../../../../../../libraries/long.js"; export default class GuiCreateWorld extends GuiScreen { @@ -25,6 +26,12 @@ export default class GuiCreateWorld extends GuiScreen { let seed = this.fieldSeed.getText(); if (seed.length === 0) { seed = new Random().nextLong(); + } else if (typeof seed === "string") { + let h = 0; + for (let i = 0; i < seed.length; i++) { + h = 31 * h + seed.charCodeAt(i); + } + seed = Long.fromNumber(h); } this.minecraft.loadWorld(new World(this.minecraft, seed)); })); diff --git a/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js b/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js index 999ec0e..7f80fe6 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js +++ b/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js @@ -64,7 +64,7 @@ export default class GuiMainMenu extends GuiScreen { this.drawLogo(stack, x, y); // Draw version - this.drawString(stack, "minecraft-js " + Minecraft.VERSION, 2, this.height - 10, 0xFFFFFF); + this.drawString(stack, "js-minecraft " + Minecraft.VERSION, 2, this.height - 10, 0xFFFFFF); // Draw copyright let mouseOver = mouseX > this.width / 2 + 70 && mouseY > this.height - 20; diff --git a/src/js/net/minecraft/client/gui/screens/GuiOptions.js b/src/js/net/minecraft/client/gui/screens/GuiOptions.js index aa1224c..9e747aa 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiOptions.js +++ b/src/js/net/minecraft/client/gui/screens/GuiOptions.js @@ -28,11 +28,14 @@ export default class GuiOptions extends GuiScreen { this.buttonList.push(new GuiSliderButton("FOV", settings.fov, 50, 100, this.width / 2 - 100, y + 24 * 2, 200, 20, value => { settings.fov = value; })); - this.buttonList.push(new GuiButton("Controls...", this.width / 2 - 100, y + 24 * 3, 200, 20, () => { + this.buttonList.push(new GuiSliderButton("Render Distance", settings.viewDistance, 2, 16, this.width / 2 - 100, y + 24 * 3, 200, 20, value => { + settings.viewDistance = value; + })); + this.buttonList.push(new GuiButton("Controls...", this.width / 2 - 100, y + 24 * 4, 200, 20, () => { this.minecraft.displayScreen(new GuiControls(this)); })); - this.buttonList.push(new GuiButton("Done", this.width / 2 - 100, y + 110, 200, 20, () => { + this.buttonList.push(new GuiButton("Done", this.width / 2 - 100, y + 130, 200, 20, () => { this.minecraft.displayScreen(this.previousScreen); })); } diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js index 8d1690a..461d506 100644 --- a/src/js/net/minecraft/client/render/WorldRenderer.js +++ b/src/js/net/minecraft/client/render/WorldRenderer.js @@ -10,7 +10,6 @@ import * as THREE from "../../../../../../libraries/three.module.js"; export default class WorldRenderer { - static RENDER_DISTANCE = 4; static THIRD_PERSON_DISTANCE = 4; constructor(minecraft, window) { @@ -48,6 +47,8 @@ export default class WorldRenderer { this.prevFogBrightness = 0; this.fogBrightness = 0; + this.flushRebuild = false; + this.initialize(); } @@ -148,6 +149,17 @@ export default class WorldRenderer { } onTick() { + // Rebuild 2 chunk sections each tick + for (let i = 0; i < 2; i++) { + if (this.chunkSectionUpdateQueue.length !== 0) { + let chunkSection = this.chunkSectionUpdateQueue.shift(); + if (chunkSection != null) { + // Rebuild chunk + chunkSection.rebuild(this); + } + } + } + this.prevFogBrightness = this.fogBrightness; this.prevEquippedProgress = this.equippedProgress; @@ -174,7 +186,7 @@ export default class WorldRenderer { // Update fog brightness let brightnessAtPosition = this.minecraft.world.getLightBrightnessForEntity(player); - let renderDistance = WorldRenderer.RENDER_DISTANCE / 32.0; + let renderDistance = this.minecraft.settings.viewDistance / 32.0; let fogBrightness = brightnessAtPosition * (1.0 - renderDistance) + renderDistance; this.fogBrightness += (fogBrightness - this.fogBrightness) * 0.1; } @@ -482,8 +494,8 @@ export default class WorldRenderer { } else { let world = this.minecraft.world; - let viewDistance = WorldRenderer.RENDER_DISTANCE * ChunkSection.SIZE; - let viewFactor = 1.0 - Math.pow(0.25 + 0.75 * WorldRenderer.RENDER_DISTANCE / 32.0, 0.25); + let viewDistance = this.minecraft.settings.viewDistance * ChunkSection.SIZE; + let viewFactor = 1.0 - Math.pow(0.25 + 0.75 * this.minecraft.settings.viewDistance / 32.0, 0.25); let angle = world.getCelestialAngle(partialTicks); @@ -538,7 +550,7 @@ export default class WorldRenderer { renderChunks(cameraChunkX, cameraChunkZ) { let world = this.minecraft.world; - let renderDistance = WorldRenderer.RENDER_DISTANCE; + let renderDistance = this.minecraft.settings.viewDistance; // Update chunks for (let [index, chunk] of world.chunks) { @@ -602,13 +614,17 @@ export default class WorldRenderer { return distance2 - distance1; }); - // Rebuild 8 chunk sections each frame - for (let i = 0; i < 8; i++) { - if (this.chunkSectionUpdateQueue.length !== 0) { - let chunkSection = this.chunkSectionUpdateQueue.shift(); - if (chunkSection != null) { - // Rebuild chunk - chunkSection.rebuild(this); + // Flush by rebuilding 8 chunk sections + if(this.flushRebuild) { + this.flushRebuild = false; + + for (let i = 0; i < 8; i++) { + if (this.chunkSectionUpdateQueue.length !== 0) { + let chunkSection = this.chunkSectionUpdateQueue.shift(); + if (chunkSection != null) { + // Rebuild chunk + chunkSection.rebuild(this); + } } } } diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index f073678..6568241 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -9,7 +9,6 @@ import Vector3 from "../../util/Vector3.js"; import Vector4 from "../../util/Vector4.js"; import MetadataChunkBlock from "../../util/MetadataChunkBlock.js"; import * as THREE from "../../../../../../libraries/three.module.js"; -import WorldRenderer from "../render/WorldRenderer.js"; import Random from "../../util/Random.js"; export default class World { @@ -652,8 +651,9 @@ export default class World { } loadSpawnChunks() { - for (let x = -WorldRenderer.RENDER_DISTANCE; x <= WorldRenderer.RENDER_DISTANCE; x++) { - for (let z = -WorldRenderer.RENDER_DISTANCE; z <= WorldRenderer.RENDER_DISTANCE; z++) { + let viewDistance = this.minecraft.settings.viewDistance; + for (let x = -viewDistance; x <= viewDistance; x++) { + for (let z = -viewDistance; z <= viewDistance; z++) { this.getChunkAt(x + this.spawn.x >> 4, z + this.spawn.z >> 4); } }