diff --git a/index.html b/index.html
index 5bf17e6..c972a8f 100644
--- a/index.html
+++ b/index.html
@@ -5,8 +5,14 @@
-
-Loading page...
+
+
+
+
+
diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js
index 744f1a8..80b3c87 100644
--- a/src/js/net/minecraft/client/GameWindow.js
+++ b/src/js/net/minecraft/client/GameWindow.js
@@ -1,6 +1,7 @@
window.GameWindow = class {
constructor(minecraft, canvasWrapperId) {
+ this.minecraft = minecraft;
this.canvasWrapperId = canvasWrapperId;
this.mouseMotionX = 0;
@@ -30,14 +31,31 @@ window.GameWindow = class {
// Mouse buttons
document.addEventListener('click', event => minecraft.onMouseClicked(event.button), false);
+ // Keyboard interaction with screen
+ window.addEventListener('keydown', function (event) {
+ if (!(minecraft.currentScreen === null)) {
+ // Handle key type on screen
+ let consumed = minecraft.currentScreen.keyTyped(event.code);
+
+ if (consumed) {
+ // Cancel browser interaction
+ event.preventDefault();
+ }
+ }
+ });
+
// Create keyboard
Keyboard.create();
}
+ requestFocus() {
+ this.renderer.canvasElement.requestPointerLock();
+ }
+
loadRenderer(renderer) {
this.renderer = renderer;
- let canvas = renderer.canvasElement;
+ let canvas = this.renderer.canvasElement;
// Add web renderer canvas to wrapper
this.wrapper.appendChild(canvas);
@@ -46,8 +64,11 @@ window.GameWindow = class {
this.onResize();
// Request focus
+ let minecraft = this.minecraft;
canvas.onclick = function () {
- canvas.requestPointerLock();
+ if (minecraft.currentScreen === null) {
+ canvas.requestPointerLock();
+ }
}
}
@@ -66,15 +87,26 @@ window.GameWindow = class {
// Reinitialize gui
this.renderer.initializeGui();
+
+ // Reinitialize current screen
+ if (!(this.minecraft.currentScreen === null)) {
+ this.minecraft.currentScreen.init(this.minecraft, this.width, this.height);
+ }
}
onFocusChanged() {
this.mouseLocked = document.pointerLockElement === this.renderer.canvasElement;
+
+ // Open in-game menu
+ if (!this.mouseLocked && this.minecraft.currentScreen === null) {
+ this.minecraft.displayScreen(new GuiIngameMenu());
+ }
}
onMouseMove(event) {
this.mouseMotionX = event.movementX;
this.mouseMotionY = -event.movementY;
+
this.mouseX = event.clientX;
this.mouseY = event.clientY;
}
diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js
index 73221cb..8ec1ec5 100644
--- a/src/js/net/minecraft/client/Minecraft.js
+++ b/src/js/net/minecraft/client/Minecraft.js
@@ -4,10 +4,22 @@ window.Minecraft = class {
* Create Minecraft instance and render it on a canvas
*/
constructor(canvasWrapperId) {
+ this.currentScreen = null;
+ this.loadingScreen = null;
+
+ // Create window and world renderer
this.window = new GameWindow(this, canvasWrapperId);
this.worldRenderer = new WorldRenderer(this, this.window);
this.timer = new Timer(20);
+ // Create current screen and overlay
+ this.ingameOverlay = new IngameOverlay(this.window);
+
+ // Display loading screen
+ this.loadingScreen = new GuiLoadingScreen();
+ this.loadingScreen.setTitle("Building terrain...");
+ this.displayScreen(this.loadingScreen);
+
this.frames = 0;
this.lastTime = Date.now();
@@ -22,10 +34,6 @@ window.Minecraft = class {
this.player = new Player(this.world);
this.pickedBlock = 1;
- // Create current screen and overlay
- this.ingameOverlay = new IngameOverlay(this.window);
- this.currentScreen = null;
-
// Initialize
this.init();
}
@@ -80,25 +88,52 @@ window.Minecraft = class {
onRender(partialTicks) {
// Player rotation
- if (this.window.mouseLocked) {
+ if (this.window.mouseLocked && !(this.currentScreen === "null")) {
this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY);
this.window.mouseMotionX = 0;
this.window.mouseMotionY = 0;
}
- while (this.world.updateLights()) ;
+ // Update lights
+ while (this.world.updateLights()) {
+ // Empty
+ }
// Render the game
this.worldRenderer.render(partialTicks);
}
+ displayScreen(screen) {
+ // Switch screen
+ this.currentScreen = screen;
+
+ // Initialize new screen
+ if (screen === null) {
+ this.window.requestFocus();
+ } else {
+ screen.init(this, this.window.width, this.window.height);
+ }
+ }
+
onTick() {
// Tick world
this.world.onTick();
// Tick the player
this.player.onTick();
+
+ // Update loading progress
+ if (!(this.loadingScreen === null)) {
+ let progress = Math.max(0, 1 - this.world.lightUpdateQueue.length / 10000);
+ this.loadingScreen.setProgress(progress);
+
+ // Finish loading
+ if (progress >= 1) {
+ this.loadingScreen = null;
+ this.displayScreen(null);
+ }
+ }
}
onMouseClicked(button) {
diff --git a/src/js/net/minecraft/client/gui/Gui.js b/src/js/net/minecraft/client/gui/Gui.js
index 96f5f81..ae0d777 100644
--- a/src/js/net/minecraft/client/gui/Gui.js
+++ b/src/js/net/minecraft/client/gui/Gui.js
@@ -1,10 +1,23 @@
window.Gui = class {
drawRect(stack, left, top, right, bottom, color, alpha = 1) {
+ stack.save();
stack.fillStyle = color;
stack.globalAlpha = alpha;
stack.fillRect(left, top, right - left, bottom - top);
- stack.globalAlpha = alpha;
+ stack.restore();
+ }
+
+ drawString(stack, string, x, y, color) {
+ this._drawString(stack, string, x, y, color, 0, false);
+ }
+
+ _drawString(stack, string, x, y, color, alignment, bold) {
+ let size = 24;
+ stack.font = (bold ? "bold" : "normal") + " " + size + "px Minecraftia";
+ stack.fillStyle = color;
+ stack.textAlign = alignment === 0 ? "center" : alignment < 0 ? "left" : "right";
+ stack.fillText(string, x, y);
}
drawTexture(stack, texture, x, y, width, height, alpha = 1.0) {
@@ -12,9 +25,21 @@ window.Gui = class {
}
drawSprite(stack, texture, spriteX, spriteY, spriteWidth, spriteHeight, x, y, width, height, alpha = 1.0) {
+ stack.save();
stack.globalAlpha = alpha;
stack.drawImage(texture, spriteX, spriteY, spriteWidth, spriteHeight, x, y, width, height);
- stack.globalAlpha = 1.0;
+ stack.restore();
+ }
+
+ drawBackground(stack, texture, width, height, scale = 8) {
+ let pattern = stack.createPattern(texture, "repeat");
+ stack.save();
+ stack.filter = "brightness(50%)";
+ stack.scale(scale, scale);
+ stack.rect(0, 0, width / scale, height / scale);
+ stack.fillStyle = pattern;
+ stack.fill();
+ stack.restore();
}
loadTexture(path) {
diff --git a/src/js/net/minecraft/client/gui/GuiScreen.js b/src/js/net/minecraft/client/gui/GuiScreen.js
index f723ed1..f802d7d 100644
--- a/src/js/net/minecraft/client/gui/GuiScreen.js
+++ b/src/js/net/minecraft/client/gui/GuiScreen.js
@@ -1,5 +1,21 @@
-window.GuiScreen = class {
+window.GuiScreen = class extends Gui {
+ init(minecraft, width, height) {
+ this.minecraft = minecraft;
+ this.width = width;
+ this.height = height;
+ }
+ drawScreen(stack, mouseX, mouseY, partialTicks) {
+
+ }
+
+ keyTyped(code) {
+ if (code === "Escape") {
+ this.minecraft.displayScreen(null);
+ return true;
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js b/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js
new file mode 100644
index 0000000..fe80bac
--- /dev/null
+++ b/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js
@@ -0,0 +1,11 @@
+window.GuiIngameMenu = class extends GuiScreen {
+
+ constructor() {
+ super();
+ }
+
+ drawScreen(stack, mouseX, mouseY, partialTicks) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js b/src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js
new file mode 100644
index 0000000..4007f75
--- /dev/null
+++ b/src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js
@@ -0,0 +1,48 @@
+window.GuiLoadingScreen = class extends GuiScreen {
+
+ constructor() {
+ super();
+
+ this.textureBackground = this.loadTexture("background.png");
+ }
+
+ drawScreen(stack, mouseX, mouseY, partialTicks) {
+ // Render dirt background
+ this.drawBackground(stack, this.textureBackground, this.width, this.height);
+
+ // Render title
+ this.drawString(stack, this.title, this.width / 2, this.height / 2 - 20, '#FFFFFF');
+
+ let progressWidth = 300;
+ let progressHeight = 5;
+
+ // Render background of progress
+ this.drawRect(
+ stack,
+ this.width / 2 - progressWidth / 2,
+ this.height / 2 - progressHeight / 2,
+ this.width / 2 + progressWidth / 2,
+ this.height / 2 + progressHeight / 2,
+ '#808080',
+ );
+
+ // Render progress
+ this.drawRect(
+ stack,
+ this.width / 2 - progressWidth / 2,
+ this.height / 2 - progressHeight / 2,
+ this.width / 2 - progressWidth / 2 + progressWidth * this.progress,
+ this.height / 2 + progressHeight / 2,
+ '#80ff80',
+ );
+ }
+
+ setTitle(title) {
+ this.title = title;
+ }
+
+ setProgress(progress) {
+ this.progress = progress;
+ }
+
+}
\ No newline at end of file
diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js
index 4c67a6a..7d70a09 100644
--- a/src/js/net/minecraft/client/render/WorldRenderer.js
+++ b/src/js/net/minecraft/client/render/WorldRenderer.js
@@ -120,6 +120,11 @@ window.WorldRenderer = class {
let mouseY = this.minecraft.window.mouseY;
this.minecraft.ingameOverlay.render(this.stack2d, mouseX, mouseY, partialTicks);
+ // Render current screen
+ if (!(this.minecraft.currentScreen === null)) {
+ this.minecraft.currentScreen.drawScreen(this.stack2d, mouseX, mouseY, partialTicks);
+ }
+
// Render actual scene and hud
this.webRenderer.render(this.scene, this.camera);
this.webRenderer.render(this.scene2d, this.camera2d);
diff --git a/src/resources/background.png b/src/resources/background.png
new file mode 100644
index 0000000..8e03ddb
Binary files /dev/null and b/src/resources/background.png differ
diff --git a/src/resources/font.ttf b/src/resources/font.ttf
new file mode 100644
index 0000000..7247ad7
Binary files /dev/null and b/src/resources/font.ttf differ
diff --git a/src/start.js b/src/start.js
index b716e6a..84a2ccc 100644
--- a/src/start.js
+++ b/src/start.js
@@ -62,6 +62,8 @@ loadScripts([
"src/js/net/minecraft/client/gui/Gui.js",
"src/js/net/minecraft/client/gui/GuiScreen.js",
"src/js/net/minecraft/client/gui/IngameOverlay.js",
+ "src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js",
+ "src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js",
"src/js/net/minecraft/client/GameWindow.js",
"src/js/net/minecraft/client/world/block/Block.js",
"src/js/net/minecraft/client/world/block/BlockStone.js",
diff --git a/style.css b/style.css
index a9b4712..2ce76c1 100644
--- a/style.css
+++ b/style.css
@@ -1,6 +1,17 @@
+@font-face {
+ font-family: "Minecraftia";
+ src: url(src/resources/font.ttf);
+}
+
body {
margin: 0;
- background-color: black;
+}
+
+#background {
+ background-image: url(background.png);
+ background-size: 128px 128px;
+ image-rendering: pixelated;
+ filter: brightness(0.5);
}
#pre-status {
@@ -16,19 +27,22 @@ body {
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none; /* Non-prefixed version, currently
- supported by Chrome, Edge, Opera and Firefox */
+ user-select: none;
+ /* Non-prefixed version, currently
+ supported by Chrome, Edge, Opera and Firefox */
/* No overflow */
white-space: nowrap;
overflow: hidden;
/* Font */
font-size: 25px;
- font-family: "FoundryGridnik", serif;
+ font-family: "Minecraftia", sans-serif;
color: white;
}
-#canvas-container {
+.fullscreen {
+ position: absolute;
+ float: left;
display: block;
width: 100%;
height: 100%;