From 32245a9136c605cbb92a3713b8010e18c8f31429 Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Tue, 17 May 2022 01:41:16 +0200 Subject: [PATCH] implement chat, implement teleport, help and time command, use relative vertex positions for block rendering, version 1.0.3 --- src/js/net/minecraft/client/GameSettings.js | 8 +- src/js/net/minecraft/client/Minecraft.js | 22 +++- .../net/minecraft/client/command/Command.js | 13 +++ .../client/command/CommandHandler.js | 34 ++++++ .../client/command/command/HelpCommand.js | 17 +++ .../client/command/command/TeleportCommand.js | 28 +++++ .../client/command/command/TimeCommand.js | 48 ++++++++ .../minecraft/client/entity/PlayerEntity.js | 16 +-- .../client/gui/overlay/ChatOverlay.js | 54 +++++++++ .../client/gui/{ => overlay}/IngameOverlay.js | 14 ++- .../minecraft/client/gui/screens/GuiChat.js | 76 ++++++++++++ .../client/gui/screens/GuiControls.js | 16 ++- .../client/gui/screens/GuiMainMenu.js | 4 +- .../client/gui/widgets/GuiTextField.js | 17 ++- .../minecraft/client/render/BlockRenderer.js | 108 ++++++++++-------- .../client/render/gui/FontRenderer.js | 12 +- .../minecraft/client/world/ChunkSection.js | 4 + src/js/net/minecraft/util/ChatLine.js | 6 + 18 files changed, 416 insertions(+), 81 deletions(-) create mode 100644 src/js/net/minecraft/client/command/Command.js create mode 100644 src/js/net/minecraft/client/command/CommandHandler.js create mode 100644 src/js/net/minecraft/client/command/command/HelpCommand.js create mode 100644 src/js/net/minecraft/client/command/command/TeleportCommand.js create mode 100644 src/js/net/minecraft/client/command/command/TimeCommand.js create mode 100644 src/js/net/minecraft/client/gui/overlay/ChatOverlay.js rename src/js/net/minecraft/client/gui/{ => overlay}/IngameOverlay.js (87%) create mode 100644 src/js/net/minecraft/client/gui/screens/GuiChat.js create mode 100644 src/js/net/minecraft/util/ChatLine.js diff --git a/src/js/net/minecraft/client/GameSettings.js b/src/js/net/minecraft/client/GameSettings.js index c56a963..3558302 100644 --- a/src/js/net/minecraft/client/GameSettings.js +++ b/src/js/net/minecraft/client/GameSettings.js @@ -1,9 +1,11 @@ export default class GameSettings { constructor() { - this.crouching = 'ShiftLeft'; - this.sprinting = 'ControlLeft'; - this.togglePerspective = 'F5'; + this.keyCrouching = 'ShiftLeft'; + this.keySprinting = 'ControlLeft'; + this.keyTogglePerspective = 'F5'; + this.keyOpenChat = 'KeyT'; + this.thirdPersonView = 0; this.fov = 70; this.viewBobbing = true; diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index f03f058..1352b90 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -4,7 +4,7 @@ import GameWindow from "./GameWindow.js"; import WorldRenderer from "./render/WorldRenderer.js"; import ScreenRenderer from "./render/gui/ScreenRenderer.js"; import ItemRenderer from "./render/gui/ItemRenderer.js"; -import IngameOverlay from "./gui/IngameOverlay.js"; +import IngameOverlay from "./gui/overlay/IngameOverlay.js"; import PlayerEntity from "./entity/PlayerEntity.js"; import SoundManager from "./sound/SoundManager.js"; import Block from "./world/block/Block.js"; @@ -16,10 +16,12 @@ import GuiMainMenu from "./gui/screens/GuiMainMenu.js"; import GuiLoadingScreen from "./gui/screens/GuiLoadingScreen.js"; import * as THREE from "../../../../../libraries/three.module.js"; import ParticleRenderer from "./render/particle/ParticleRenderer.js"; +import GuiChat from "./gui/screens/GuiChat.js"; +import CommandHandler from "./command/CommandHandler.js"; export default class Minecraft { - static VERSION = "1.0.2" + static VERSION = "1.0.3" static URL_GITHUB = "https://github.com/labystudio/js-minecraft"; /** @@ -52,6 +54,9 @@ export default class Minecraft { // Create current screen and overlay this.ingameOverlay = new IngameOverlay(this, this.window); + // Command handler + this.commandHandler = new CommandHandler(this); + this.frames = 0; this.lastTime = Date.now(); @@ -125,6 +130,10 @@ export default class Minecraft { return this.world !== null && this.worldRenderer !== null && this.player !== null; } + addMessageToChat(message) { + this.ingameOverlay.chatOverlay.addMessage(message); + } + requestNextFrame() { requestAnimationFrame(() => { if (this.running) { @@ -225,6 +234,9 @@ export default class Minecraft { // Tick particle renderer this.particleRenderer.onTick(); + + // Tick overlay + this.ingameOverlay.onTick(); } // Tick the screen @@ -269,10 +281,14 @@ export default class Minecraft { } } - if (button === this.settings.togglePerspective) { + if (button === this.settings.keyTogglePerspective) { this.settings.thirdPersonView = (this.settings.thirdPersonView + 1) % 3; this.settings.save(); } + + if (button === this.settings.keyOpenChat) { + this.displayScreen(new GuiChat()); + } } onMouseClicked(button) { diff --git a/src/js/net/minecraft/client/command/Command.js b/src/js/net/minecraft/client/command/Command.js new file mode 100644 index 0000000..49f751b --- /dev/null +++ b/src/js/net/minecraft/client/command/Command.js @@ -0,0 +1,13 @@ +export default class Command { + + constructor(command, usage, description) { + this.command = command; + this.usage = usage; + this.description = description; + } + + execute(minecraft, args) { + return false; + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/command/CommandHandler.js b/src/js/net/minecraft/client/command/CommandHandler.js new file mode 100644 index 0000000..c328896 --- /dev/null +++ b/src/js/net/minecraft/client/command/CommandHandler.js @@ -0,0 +1,34 @@ +import HelpCommand from "./command/HelpCommand.js"; +import TimeCommand from "./command/TimeCommand.js"; +import TeleportCommand from "./command/TeleportCommand.js"; + +export default class CommandHandler { + + constructor(minecraft) { + this.minecraft = minecraft; + + this.commands = []; + this.commands.push(new HelpCommand()); + this.commands.push(new TimeCommand()); + this.commands.push(new TeleportCommand()); + } + + handleMessage(message) { + let args = message.split(" "); + let command = args[0].toLowerCase(); + this.handleCommand(command, args.slice(1)); + } + + handleCommand(command, args) { + for (let i = 0; i < this.commands.length; i++) { + let commandExecutor = this.commands[i]; + if (commandExecutor.command === command) { + if (!this.commands[i].execute(this.minecraft, args)) { + this.minecraft.addMessageToChat("/" + commandExecutor.command + " " + commandExecutor.usage); + } + return; + } + } + this.minecraft.addMessageToChat("Unknown command! Type \"/help\" for help."); + } +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/command/command/HelpCommand.js b/src/js/net/minecraft/client/command/command/HelpCommand.js new file mode 100644 index 0000000..3e48894 --- /dev/null +++ b/src/js/net/minecraft/client/command/command/HelpCommand.js @@ -0,0 +1,17 @@ +import Command from "../Command.js"; + +export default class HelpCommand extends Command { + + constructor() { + super("help", "", "Displays a list of commands") + } + + execute(minecraft, args) { + minecraft.addMessageToChat("&2--- Showing help page ---"); + minecraft.commandHandler.commands.forEach(command => { + minecraft.addMessageToChat("/" + command.command + " " + command.usage + " - " + command.description); + }); + return true; + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/command/command/TeleportCommand.js b/src/js/net/minecraft/client/command/command/TeleportCommand.js new file mode 100644 index 0000000..c284a16 --- /dev/null +++ b/src/js/net/minecraft/client/command/command/TeleportCommand.js @@ -0,0 +1,28 @@ +import Command from "../Command.js"; + +export default class TeleportCommand extends Command { + + constructor() { + super("tp", " ", "Teleport to a position") + } + + execute(minecraft, args) { + if (args.length !== 3) { + return false; + } + + let x = parseInt(args[0]); + let y = parseInt(args[1]); + let z = parseInt(args[2]); + + if (isNaN(x) || isNaN(y) || isNaN(z)) { + return false; + } + + minecraft.player.setPosition(x, y, z); + minecraft.addMessageToChat("Teleported to " + x + " " + y + " " + z); + + return true; + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/command/command/TimeCommand.js b/src/js/net/minecraft/client/command/command/TimeCommand.js new file mode 100644 index 0000000..4599bb6 --- /dev/null +++ b/src/js/net/minecraft/client/command/command/TimeCommand.js @@ -0,0 +1,48 @@ +import Command from "../Command.js"; + +export default class TimeCommand extends Command { + + constructor() { + super("time", " ", "Change the time of the world") + } + + execute(minecraft, args) { + if (args.length !== 2) { + return false; + } + + let action = args[0]; + let value = args[1]; + + if (action === "add") { + if (isNaN(value)) { + return false; + } else { + value = parseInt(value); + } + + minecraft.world.time += value; + minecraft.addMessageToChat("Added " + value + " to the time"); + } else if (action === "set") { + if (isNaN(value)) { + if (value === "day") { + value = 1000; + } else if (value === "night") { + value = 13000; + } else { + return false; + } + } else { + value = parseInt(value); + } + + minecraft.world.time = value; + minecraft.addMessageToChat("Time set to " + value); + } else { + return false; + } + + return true; + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/entity/PlayerEntity.js b/src/js/net/minecraft/client/entity/PlayerEntity.js index 81bcb2d..e693d92 100644 --- a/src/js/net/minecraft/client/entity/PlayerEntity.js +++ b/src/js/net/minecraft/client/entity/PlayerEntity.js @@ -304,32 +304,32 @@ export default class PlayerEntity extends EntityLiving { let sneaking = false; if (this.minecraft.hasInGameFocus()) { - if (Keyboard.isKeyDown("KeyR")) { // R + if (Keyboard.isKeyDown("KeyR")) { // this.respawn(); } - if (Keyboard.isKeyDown("KeyW")) { // W + if (Keyboard.isKeyDown("KeyW")) { moveForward++; } - if (Keyboard.isKeyDown("KeyS")) { // S + if (Keyboard.isKeyDown("KeyS")) { moveForward--; } - if (Keyboard.isKeyDown("KeyA")) { // A + if (Keyboard.isKeyDown("KeyA")) { moveStrafe++; } - if (Keyboard.isKeyDown("KeyD")) { // D + if (Keyboard.isKeyDown("KeyD")) { moveStrafe--; } - if (Keyboard.isKeyDown("Space")) { // Space + if (Keyboard.isKeyDown("Space")) { jumping = true; } - if (Keyboard.isKeyDown(this.minecraft.settings.sprinting)) { + if (Keyboard.isKeyDown(this.minecraft.settings.keySprinting)) { if (this.moveForward > 0 && !this.sneaking && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) { this.sprinting = true; this.updateFOVModifier(); } } - if (Keyboard.isKeyDown(this.minecraft.settings.crouching)) { // Q + if (Keyboard.isKeyDown(this.minecraft.settings.keyCrouching)) { sneaking = true; } diff --git a/src/js/net/minecraft/client/gui/overlay/ChatOverlay.js b/src/js/net/minecraft/client/gui/overlay/ChatOverlay.js new file mode 100644 index 0000000..2d2f903 --- /dev/null +++ b/src/js/net/minecraft/client/gui/overlay/ChatOverlay.js @@ -0,0 +1,54 @@ +import Gui from "../Gui.js"; +import ChatLine from "../../../util/ChatLine.js"; +import GuiChat from "../screens/GuiChat.js"; +import MathHelper from "../../../util/MathHelper.js"; + +export default class ChatOverlay extends Gui { + + constructor(minecraft) { + super(minecraft); + + this.messages = []; + this.sentHistory = []; + } + + render(stack, mouseX, mouseY, partialTicks) { + let chatOpen = this.minecraft.currentScreen instanceof GuiChat; + + for (let i = 0; i < this.messages.length; i++) { + let message = this.messages[i]; + if (message.updateCounter >= 200 && !chatOpen) { + continue; + } + + let opacity = MathHelper.clamp((1.0 - message.updateCounter / 200) * 10, 0.0, 1.0); + let alpha = Math.floor(255 * opacity * opacity); + if (chatOpen) { + alpha = 255; + } + + if (alpha > 0) { + let y = this.minecraft.window.height - 40 - i * 9; + + this.drawRect(stack, 2, y - 1, 2 + 320, y + 8, '#000000', alpha / 2 / 255); + this.drawString(stack, message.message, 2, y, 0xffffff + (alpha << 24)); + } + } + } + + onTick() { + for (let i = 0; i < this.messages.length; i++) { + let message = this.messages[i]; + message.updateCounter++; + } + } + + addMessage(message) { + this.messages.splice(0, 0, new ChatLine(message)); + } + + addMessageToSentHistory(message) { + this.sentHistory.splice(0, 0, message); + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/gui/IngameOverlay.js b/src/js/net/minecraft/client/gui/overlay/IngameOverlay.js similarity index 87% rename from src/js/net/minecraft/client/gui/IngameOverlay.js rename to src/js/net/minecraft/client/gui/overlay/IngameOverlay.js index 2fa8c5d..ffae23d 100644 --- a/src/js/net/minecraft/client/gui/IngameOverlay.js +++ b/src/js/net/minecraft/client/gui/overlay/IngameOverlay.js @@ -1,5 +1,6 @@ -import Gui from "./Gui.js"; -import Block from "../world/block/Block.js"; +import Gui from "../Gui.js"; +import Block from "../../world/block/Block.js"; +import ChatOverlay from "./ChatOverlay.js"; export default class IngameOverlay extends Gui { @@ -8,6 +9,8 @@ export default class IngameOverlay extends Gui { this.minecraft = minecraft; this.window = window; + this.chatOverlay = new ChatOverlay(minecraft); + this.textureCrosshair = minecraft.resources["gui/icons.png"]; this.textureHotbar = minecraft.resources["gui/gui.png"]; } @@ -21,6 +24,9 @@ export default class IngameOverlay extends Gui { // Render hotbar this.renderHotbar(stack, this.window.width / 2 - 91, this.window.height - 22); + // Render chat + this.chatOverlay.render(stack, mouseX, mouseY, partialTicks); + let world = this.minecraft.world; let player = this.minecraft.player; @@ -38,6 +44,10 @@ export default class IngameOverlay extends Gui { this.drawString(stack, x + ", " + y + ", " + z + " (" + (x >> 4) + ", " + (y >> 4) + ", " + (z >> 4) + ")", 1, 1 + 9); } + onTick() { + this.chatOverlay.onTick(); + } + renderCrosshair(stack, x, y) { let size = 15; this.drawSprite(stack, this.textureCrosshair, 0, 0, 15, 15, x - size / 2, y - size / 2, size, size, 0.6); diff --git a/src/js/net/minecraft/client/gui/screens/GuiChat.js b/src/js/net/minecraft/client/gui/screens/GuiChat.js new file mode 100644 index 0000000..2912fc1 --- /dev/null +++ b/src/js/net/minecraft/client/gui/screens/GuiChat.js @@ -0,0 +1,76 @@ +import GuiScreen from "../GuiScreen.js"; +import GuiTextField from "../widgets/GuiTextField.js"; + +export default class GuiChat extends GuiScreen { + + constructor() { + super(); + + this.inputField = new GuiTextField(0, 0, 0, 0); + this.inputField.renderBackground = false; + + this.historyIndex = -1; + } + + init() { + super.init(); + + this.inputField.x = 2; + this.inputField.y = this.height - 14; + this.inputField.width = this.width - 4; + this.inputField.height = 12; + this.inputField.isFocused = true; + + this.buttonList.push(this.inputField); + } + + drawScreen(stack, mouseX, mouseY, partialTicks) { + this.drawRect(stack, 2, this.height - 14, this.width - 2, this.height - 2, '#000000', 0.5); + + super.drawScreen(stack, mouseX, mouseY, partialTicks); + } + + keyTyped(key, character) { + if (key === "Enter") { + let message = this.inputField.getText().trim(); + if (message.length === 0) { + return; + } + + // Close screen + this.minecraft.displayScreen(null); + + // Add message to sent history + this.minecraft.ingameOverlay.chatOverlay.addMessageToSentHistory(message); + + // Handle message + if (message.startsWith("/")) { + this.minecraft.commandHandler.handleMessage(message.substring(1)); + } else { + this.minecraft.addMessageToChat(message); + } + return; + } + + if (key === "ArrowUp" || key === "ArrowDown") { + let up = key === "ArrowUp"; + let history = this.minecraft.ingameOverlay.chatOverlay.sentHistory; + + if (up) { + if (this.historyIndex + 1 < history.length) { + this.historyIndex++; + } + } else { + if (this.historyIndex >= 0) { + this.historyIndex--; + } + } + + this.inputField.text = this.historyIndex < 0 ? "" : history[this.historyIndex]; + return; + } + + return super.keyTyped(key, character); + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/gui/screens/GuiControls.js b/src/js/net/minecraft/client/gui/screens/GuiControls.js index 9c73be3..d1a2f0d 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiControls.js +++ b/src/js/net/minecraft/client/gui/screens/GuiControls.js @@ -23,16 +23,20 @@ export default class GuiControls extends GuiScreen { return name + ": " + value + "%"; })); - this.buttonList.push(new GuiKeyButton("Crouch", settings.crouching, this.width / 2 - 100, y + 24, 200, 20, key => { - settings.crouching = key; + this.buttonList.push(new GuiKeyButton("Crouch", settings.keyCrouching, this.width / 2 - 100, y + 24, 200, 20, key => { + settings.keyCrouching = key; })); - this.buttonList.push(new GuiKeyButton("Sprint", settings.sprinting, this.width / 2 - 100, y + 24 * 2, 200, 20, key => { - settings.sprinting = key; + this.buttonList.push(new GuiKeyButton("Sprint", settings.keySprinting, this.width / 2 - 100, y + 24 * 2, 200, 20, key => { + settings.keySprinting = key; })); - this.buttonList.push(new GuiKeyButton("Toggle Perspective", settings.togglePerspective, this.width / 2 - 100, y + 24 * 3, 200, 20, key => { - settings.togglePerspective = key; + this.buttonList.push(new GuiKeyButton("Toggle Perspective", settings.keyTogglePerspective, this.width / 2 - 100, y + 24 * 3, 200, 20, key => { + settings.keyTogglePerspective = key; + })); + + this.buttonList.push(new GuiKeyButton("Open Chat", settings.keyOpenChat, this.width / 2 - 100, y + 24 * 4, 200, 20, key => { + settings.keyOpenChat = key; })); this.buttonList.push(new GuiButton("Done", this.width / 2 - 100, y + 130, 200, 20, () => { diff --git a/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js b/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js index 7f80fe6..11e6e33 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js +++ b/src/js/net/minecraft/client/gui/screens/GuiMainMenu.js @@ -64,11 +64,11 @@ export default class GuiMainMenu extends GuiScreen { this.drawLogo(stack, x, y); // Draw version - this.drawString(stack, "js-minecraft " + Minecraft.VERSION, 2, this.height - 10, 0xFFFFFF); + this.drawString(stack, "js-minecraft " + Minecraft.VERSION, 2, this.height - 10, 0xFFFFFFff); // Draw copyright let mouseOver = mouseX > this.width / 2 + 70 && mouseY > this.height - 20; - this.drawRightString(stack, "GitHub @LabyStudio/js-minecraft", this.width - 2, this.height - 10, mouseOver ? 0x0000FF : 0xFFFFFF); + this.drawRightString(stack, "GitHub @LabyStudio/js-minecraft", this.width - 2, this.height - 10, mouseOver ? 0x0000FFFF : 0xFFFFFFff); // Draw buttons super.drawScreen(stack, mouseX, mouseY, partialTicks); diff --git a/src/js/net/minecraft/client/gui/widgets/GuiTextField.js b/src/js/net/minecraft/client/gui/widgets/GuiTextField.js index 1b10264..ed0ef03 100644 --- a/src/js/net/minecraft/client/gui/widgets/GuiTextField.js +++ b/src/js/net/minecraft/client/gui/widgets/GuiTextField.js @@ -9,15 +9,18 @@ export default class GuiTextField extends GuiButton { this.isFocused = false; this.cursorCounter = 0; this.maxLength = 80; + this.renderBackground = true; } render(stack, mouseX, mouseY, partialTicks) { let cursorVisible = this.isFocused && Math.floor(this.cursorCounter / 6) % 2 === 0; - let textColor = this.enabled ? 14737632 : 7368816; + let textColor = this.enabled ? 0xe0e0e0ff : 0x707070ff; // Draw background - this.drawRect(stack, this.x - 1, this.y - 1, this.x + this.width + 1, this.y + this.height + 1, '#5f5f60'); - this.drawRect(stack, this.x, this.y, this.x + this.width, this.y + this.height, 'black'); + if (this.renderBackground) { + this.drawRect(stack, this.x - 1, this.y - 1, this.x + this.width + 1, this.y + this.height + 1, '#5f5f60'); + this.drawRect(stack, this.x, this.y, this.x + this.width, this.y + this.height, 'black'); + } // Draw text this.drawString(stack, this.text, this.x + 2, this.y + this.height / 2 - 4, textColor); @@ -41,6 +44,10 @@ export default class GuiTextField extends GuiButton { } keyTyped(key, character) { + if (!this.isFocused || !this.enabled) { + return; + } + if (key === "Backspace") { if (this.text.length > 0) { this.text = this.text.substring(0, this.text.length - 1); @@ -70,6 +77,10 @@ export default class GuiTextField extends GuiButton { return; } + if (character.length !== 1) { + return; + } + if (this.text.length < this.maxLength) { this.text += character; } diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index 51d931c..f3ceed6 100644 --- a/src/js/net/minecraft/client/render/BlockRenderer.js +++ b/src/js/net/minecraft/client/render/BlockRenderer.js @@ -41,6 +41,10 @@ export default class BlockRenderer { } renderFace(world, block, boundingBox, face, ambientOcclusion, x, y, z) { + let chunkX = x >> 4; + let chunkY = y >> 4; + let chunkZ = z >> 4; + // Vertex mappings let minX = x + boundingBox.minX; let minY = y + boundingBox.minY; @@ -78,55 +82,55 @@ export default class BlockRenderer { // this.tessellator.setAlpha(1 - block.getTransparency()); // Add face to tessellator - this.addFace(world, face, ambientOcclusion, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, red, green, blue); + this.addFace(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, red, green, blue); } - addFace(world, face, ambientOcclusion, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, red = 1, green = 1, blue = 1) { + addFace(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, red = 1, green = 1, blue = 1) { if (face === EnumBlockFace.BOTTOM) { - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, maxZ, maxU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, minZ, maxU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, minZ, minU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, maxZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, maxZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, minZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, maxZ, minU, maxV, red, green, blue); } if (face === EnumBlockFace.TOP) { - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, maxZ, minU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, minZ, minU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, minZ, maxU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, maxZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, maxZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, minZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, minZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, maxZ, maxU, maxV, red, green, blue); } if (face === EnumBlockFace.NORTH) { - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, minZ, minU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, minZ, minU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, minZ, maxU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, minZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, minZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, minZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, minZ, maxU, minV, red, green, blue); } if (face === EnumBlockFace.SOUTH) { - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, maxZ, maxU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, maxZ, minU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, maxZ, minU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, maxZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, maxZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, maxZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, maxZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, maxZ, maxU, maxV, red, green, blue); } if (face === EnumBlockFace.WEST) { - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, maxZ, minU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, minY, minZ, maxU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, minZ, maxU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, maxZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, maxZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, minZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, maxZ, minU, minV, red, green, blue); } if (face === EnumBlockFace.EAST) { - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, maxZ, maxU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, minZ, minU, minV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, minZ, minU, maxV, red, green, blue); - this.addBlockCorner(world, face, ambientOcclusion, maxX, minY, maxZ, maxU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, maxZ, maxU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, minZ, minU, minV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, minZ, minU, maxV, red, green, blue); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, minY, maxZ, maxU, maxV, red, green, blue); } } - addBlockCorner(world, face, ambientOcclusion, x, y, z, u, v, red, green, blue) { + addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, x, y, z, u, v, red, green, blue) { // Smooth lightning if (ambientOcclusion) { this.setAverageBrightness(world, face, x, y, z, red, green, blue); } - this.tessellator.addVertexWithUV(x, y, z, u, v); + this.tessellator.addVertexWithUV(x - (chunkX << 4), y - (chunkY << 4), z - (chunkZ << 4), u, v); } setAverageBrightness(world, face, x, y, z, red = 1, green = 1, blue = 1) { @@ -176,6 +180,10 @@ export default class BlockRenderer { } renderTorch(world, block, x, y, z) { + let chunkX = x >> 4; + let chunkY = y >> 4; + let chunkZ = z >> 4; + // Thickness of the torch let size = 1 / 16; @@ -238,37 +246,37 @@ export default class BlockRenderer { this.tessellator.setColor(1, 1, 1); // Add faces to tessellator - this.addDistortFace(world, EnumBlockFace.NORTH, false, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); - this.addDistortFace(world, EnumBlockFace.EAST, false, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); - this.addDistortFace(world, EnumBlockFace.SOUTH, false, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); - this.addDistortFace(world, EnumBlockFace.WEST, false, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); - this.addFace(world, EnumBlockFace.TOP, false, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV + 8 / 256); + this.addDistortFace(world, EnumBlockFace.NORTH, false, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); + this.addDistortFace(world, EnumBlockFace.EAST, false, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); + this.addDistortFace(world, EnumBlockFace.SOUTH, false, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); + this.addDistortFace(world, EnumBlockFace.WEST, false, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ); + this.addFace(world, EnumBlockFace.TOP, false, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV + 8 / 256); } - addDistortFace(world, face, ambientOcclusion, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ) { + addDistortFace(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, minY, minZ, maxX, maxY, maxZ, minU, minV, maxU, maxV, distortX, distortZ) { if (face === EnumBlockFace.NORTH) { - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, minZ, minU, minV); - this.addBlockCorner(world, face, ambientOcclusion, minX + distortX, minY, minZ + distortZ, minU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, maxX + distortX, minY, minZ + distortZ, maxU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, minZ, maxU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, minZ, minU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX + distortX, minY, minZ + distortZ, minU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX + distortX, minY, minZ + distortZ, maxU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, minZ, maxU, minV); } if (face === EnumBlockFace.SOUTH) { - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, maxZ, maxU, minV); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, maxZ, minU, minV); - this.addBlockCorner(world, face, ambientOcclusion, maxX + distortX, minY, maxZ + distortZ, minU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, minX + distortX, minY, maxZ + distortZ, maxU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, maxZ, maxU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, maxZ, minU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX + distortX, minY, maxZ + distortZ, minU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX + distortX, minY, maxZ + distortZ, maxU, maxV); } if (face === EnumBlockFace.WEST) { - this.addBlockCorner(world, face, ambientOcclusion, minX + distortX, minY, maxZ + distortZ, minU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, minX + distortX, minY, minZ + distortZ, maxU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, minZ, maxU, minV); - this.addBlockCorner(world, face, ambientOcclusion, minX, maxY, maxZ, minU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX + distortX, minY, maxZ + distortZ, minU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX + distortX, minY, minZ + distortZ, maxU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, minZ, maxU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, minX, maxY, maxZ, minU, minV); } if (face === EnumBlockFace.EAST) { - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, maxZ, maxU, minV); - this.addBlockCorner(world, face, ambientOcclusion, maxX, maxY, minZ, minU, minV); - this.addBlockCorner(world, face, ambientOcclusion, maxX + distortX, minY, minZ + distortZ, minU, maxV); - this.addBlockCorner(world, face, ambientOcclusion, maxX + distortX, minY, maxZ + distortZ, maxU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, maxZ, maxU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX, maxY, minZ, minU, minV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX + distortX, minY, minZ + distortZ, minU, maxV); + this.addBlockCorner(world, face, ambientOcclusion, chunkX, chunkY, chunkZ, maxX + distortX, minY, maxZ + distortZ, maxU, maxV); } } diff --git a/src/js/net/minecraft/client/render/gui/FontRenderer.js b/src/js/net/minecraft/client/render/gui/FontRenderer.js index cd3c72d..5b59693 100644 --- a/src/js/net/minecraft/client/render/gui/FontRenderer.js +++ b/src/js/net/minecraft/client/render/gui/FontRenderer.js @@ -62,10 +62,13 @@ export default class FontRenderer { this.setColor(stack, color, isShadow); } + let alpha = ((color & 0xFF000000) >>> 24) / 255; + // For each character for (let i = 0; i < string.length; i++) { let character = string[i]; - let code = string[i].charCodeAt(0); + let index = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000".indexOf(character); + let code = character.charCodeAt(0); // Handle color codes if character is & if (character === '&' && i !== string.length - 1) { @@ -81,8 +84,8 @@ export default class FontRenderer { } // Get character offset in bitmap - let textureOffsetX = code % FontRenderer.BITMAP_SIZE * FontRenderer.FIELD_SIZE; - let textureOffsetY = Math.floor(code / FontRenderer.BITMAP_SIZE) * FontRenderer.FIELD_SIZE; + let textureOffsetX = index % FontRenderer.BITMAP_SIZE * FontRenderer.FIELD_SIZE; + let textureOffsetY = Math.floor(index / FontRenderer.BITMAP_SIZE) * FontRenderer.FIELD_SIZE; // Draw character Gui.drawSprite( @@ -91,7 +94,8 @@ export default class FontRenderer { textureOffsetX, textureOffsetY, FontRenderer.FIELD_SIZE, FontRenderer.FIELD_SIZE, Math.floor(x), Math.floor(y), - FontRenderer.FIELD_SIZE, FontRenderer.FIELD_SIZE + FontRenderer.FIELD_SIZE, FontRenderer.FIELD_SIZE, + alpha ); // Increase drawing cursor diff --git a/src/js/net/minecraft/client/world/ChunkSection.js b/src/js/net/minecraft/client/world/ChunkSection.js index b64bbb5..56f85a4 100644 --- a/src/js/net/minecraft/client/world/ChunkSection.js +++ b/src/js/net/minecraft/client/world/ChunkSection.js @@ -23,6 +23,10 @@ export default class ChunkSection { this.boundingBox.max.z = z * ChunkSection.SIZE + ChunkSection.SIZE; this.group = new THREE.Object3D(); + this.group.position.x = this.x * ChunkSection.SIZE; + this.group.position.y = this.y * ChunkSection.SIZE; + this.group.position.z = this.z * ChunkSection.SIZE; + this.group.updateMatrix(); this.group.matrixAutoUpdate = false; this.isModified = true; diff --git a/src/js/net/minecraft/util/ChatLine.js b/src/js/net/minecraft/util/ChatLine.js new file mode 100644 index 0000000..c9f7ab3 --- /dev/null +++ b/src/js/net/minecraft/util/ChatLine.js @@ -0,0 +1,6 @@ +export default class ChatLine { + constructor(message) { + this.message = message; + this.updateCounter = 0; + } +} \ No newline at end of file