From 5eb1d03e5d8f71404afafab6c8c4be95e28568d0 Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Thu, 3 Feb 2022 16:02:55 +0100 Subject: [PATCH] implement ingame menu --- src/js/net/minecraft/client/GameWindow.js | 36 ++++++++-- src/js/net/minecraft/client/Minecraft.js | 10 ++- src/js/net/minecraft/client/entity/Player.js | 65 +++++++++--------- src/js/net/minecraft/client/gui/Gui.js | 26 +++++-- src/js/net/minecraft/client/gui/GuiScreen.js | 29 +++++++- .../net/minecraft/client/gui/IngameOverlay.js | 2 +- .../client/gui/screens/GuiIngameMenu.js | 17 ++++- .../client/gui/screens/GuiLoadingScreen.js | 4 +- .../minecraft/client/gui/widgets/GuiButton.js | 30 ++++++++ src/js/net/minecraft/client/world/World.js | 27 +++----- src/resources/gui.png | Bin 0 -> 8645 bytes src/resources/terrain.png | Bin 6686 -> 7547 bytes src/start.js | 1 + style.css | 1 + 14 files changed, 179 insertions(+), 69 deletions(-) create mode 100644 src/js/net/minecraft/client/gui/widgets/GuiButton.js create mode 100644 src/resources/gui.png diff --git a/src/js/net/minecraft/client/GameWindow.js b/src/js/net/minecraft/client/GameWindow.js index 80b3c87..1af33a3 100644 --- a/src/js/net/minecraft/client/GameWindow.js +++ b/src/js/net/minecraft/client/GameWindow.js @@ -28,8 +28,23 @@ window.GameWindow = class { // Mouse motion document.addEventListener('mousemove', event => this.onMouseMove(event), false); + // Losing focus event + window.addEventListener("mouseout", function () { + if (minecraft.currentScreen === null) { + minecraft.displayScreen(new GuiIngameMenu()); + } + }); + // Mouse buttons - document.addEventListener('click', event => minecraft.onMouseClicked(event.button), false); + document.addEventListener('click', function (event) { + // Handle in-game mouse click + minecraft.onMouseClicked(event.button); + + // Handle mouse click on screen + if (!(minecraft.currentScreen === null)) { + minecraft.currentScreen.mouseClicked(event.x, event.y, event.code); + } + }, false); // Keyboard interaction with screen window.addEventListener('keydown', function (event) { @@ -41,6 +56,9 @@ window.GameWindow = class { // Cancel browser interaction event.preventDefault(); } + } else if (event.code === 'Escape') { + event.preventDefault(); + minecraft.displayScreen(new GuiIngameMenu()); } }); @@ -49,7 +67,12 @@ window.GameWindow = class { } requestFocus() { - this.renderer.canvasElement.requestPointerLock(); + let scope = this; + + setTimeout(function () { + window.focus(); + scope.renderer.canvasElement.requestPointerLock(); + }, 0); } loadRenderer(renderer) { @@ -64,10 +87,10 @@ window.GameWindow = class { this.onResize(); // Request focus - let minecraft = this.minecraft; + let scope = this; canvas.onclick = function () { - if (minecraft.currentScreen === null) { - canvas.requestPointerLock(); + if (scope.minecraft.currentScreen === null) { + scope.requestFocus(); } } } @@ -90,14 +113,13 @@ window.GameWindow = class { // Reinitialize current screen if (!(this.minecraft.currentScreen === null)) { - this.minecraft.currentScreen.init(this.minecraft, this.width, this.height); + this.minecraft.currentScreen.setup(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()); } diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index 8ec1ec5..d5550bc 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -31,7 +31,7 @@ window.Minecraft = class { this.worldRenderer.scene.add(this.world.group); // Create player - this.player = new Player(this.world); + this.player = new Player(this, this.world); this.pickedBlock = 1; // Initialize @@ -48,6 +48,10 @@ window.Minecraft = class { this.requestNextFrame(); } + hasInGameFocus() { + return this.window.mouseLocked && this.currentScreen === null; + } + requestNextFrame() { let scope = this; requestAnimationFrame(function () { @@ -88,7 +92,7 @@ window.Minecraft = class { onRender(partialTicks) { // Player rotation - if (this.window.mouseLocked && !(this.currentScreen === "null")) { + if (this.hasInGameFocus()) { this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY); this.window.mouseMotionX = 0; @@ -112,7 +116,7 @@ window.Minecraft = class { if (screen === null) { this.window.requestFocus(); } else { - screen.init(this, this.window.width, this.window.height); + screen.setup(this, this.window.width, this.window.height); } } diff --git a/src/js/net/minecraft/client/entity/Player.js b/src/js/net/minecraft/client/entity/Player.js index f397385..21c7b3d 100644 --- a/src/js/net/minecraft/client/entity/Player.js +++ b/src/js/net/minecraft/client/entity/Player.js @@ -1,6 +1,7 @@ window.Player = class { - constructor(world) { + constructor(minecraft, world) { + this.minecraft = minecraft; this.world = world; this.prevX = 0; @@ -309,38 +310,40 @@ window.Player = class { let jumping = false; let sneaking = false; - if (Keyboard.isKeyDown("KeyR")) { // R - this.respawn(); - } - if (Keyboard.isKeyDown("KeyW")) { // W - moveForward++; - } - if (Keyboard.isKeyDown("KeyS")) { // S - moveForward--; - } - if (Keyboard.isKeyDown("KeyA")) { // A - moveStrafe++; - } - if (Keyboard.isKeyDown("KeyD")) { // D - moveStrafe--; - } - if (Keyboard.isKeyDown("Space")) { // Space - jumping = true; - } - if (Keyboard.isKeyDown("ShiftLeft")) { // Shift - if (this.moveForward > 0 && !this.sneaking && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) { - this.sprinting = true; - - this.updateFOVModifier(); + if (this.minecraft.hasInGameFocus()) { + if (Keyboard.isKeyDown("KeyR")) { // R + this.respawn(); } - } - if (Keyboard.isKeyDown("KeyQ")) { // Q - sneaking = true; - } + if (Keyboard.isKeyDown("KeyW")) { // W + moveForward++; + } + if (Keyboard.isKeyDown("KeyS")) { // S + moveForward--; + } + if (Keyboard.isKeyDown("KeyA")) { // A + moveStrafe++; + } + if (Keyboard.isKeyDown("KeyD")) { // D + moveStrafe--; + } + if (Keyboard.isKeyDown("Space")) { // Space + jumping = true; + } + if (Keyboard.isKeyDown("ShiftLeft")) { // Shift + if (this.moveForward > 0 && !this.sneaking && !this.sprinting && this.motionX !== 0 && this.motionZ !== 0) { + this.sprinting = true; - if (sneaking) { - moveStrafe = moveStrafe * 0.3; - moveForward = moveForward * 0.3; + this.updateFOVModifier(); + } + } + if (Keyboard.isKeyDown("KeyQ")) { // Q + sneaking = true; + } + + if (sneaking) { + moveStrafe = moveStrafe * 0.3; + moveForward = moveForward * 0.3; + } } this.moveForward = moveForward; diff --git a/src/js/net/minecraft/client/gui/Gui.js b/src/js/net/minecraft/client/gui/Gui.js index ae0d777..7d1afd3 100644 --- a/src/js/net/minecraft/client/gui/Gui.js +++ b/src/js/net/minecraft/client/gui/Gui.js @@ -1,5 +1,7 @@ window.Gui = class { + static FONT = "normal 20px Minecraftia"; + drawRect(stack, left, top, right, bottom, color, alpha = 1) { stack.save(); stack.fillStyle = color; @@ -8,18 +10,28 @@ window.Gui = class { stack.restore(); } - drawString(stack, string, x, y, color) { - this._drawString(stack, string, x, y, color, 0, false); + drawCenteredString(stack, string, x, y, color = 'white') { + this._drawString(stack, string, x + this.getStringWidth(stack, string) / 2, y, color, 1); } - _drawString(stack, string, x, y, color, alignment, bold) { - let size = 24; - stack.font = (bold ? "bold" : "normal") + " " + size + "px Minecraftia"; - stack.fillStyle = color; + drawString(stack, string, x, y, color = 'white') { + this._drawString(stack, string, x, y, color, 0); + } + + _drawString(stack, string, x, y, color, alignment) { + stack.font = Gui.FONT; + stack.fillStyle = 'black'; stack.textAlign = alignment === 0 ? "center" : alignment < 0 ? "left" : "right"; + stack.fillText(string, x + 2, y + 2); + stack.fillStyle = color; stack.fillText(string, x, y); } + getStringWidth(stack, string) { + stack.font = Gui.FONT; + return stack.measureText(string).width; + } + drawTexture(stack, texture, x, y, width, height, alpha = 1.0) { this.drawSprite(stack, texture, 0, 0, 256, 256, x, y, width, height, alpha); } @@ -42,7 +54,7 @@ window.Gui = class { stack.restore(); } - loadTexture(path) { + static loadTexture(path) { let img = new Image(); img.src = path; return img; diff --git a/src/js/net/minecraft/client/gui/GuiScreen.js b/src/js/net/minecraft/client/gui/GuiScreen.js index f802d7d..84e62a7 100644 --- a/src/js/net/minecraft/client/gui/GuiScreen.js +++ b/src/js/net/minecraft/client/gui/GuiScreen.js @@ -1,13 +1,28 @@ window.GuiScreen = class extends Gui { - init(minecraft, width, height) { + constructor() { + super(); + + this.buttonList = []; + } + + setup(minecraft, width, height) { this.minecraft = minecraft; this.width = width; this.height = height; + + this.init(); + } + + init() { + this.buttonList = []; } drawScreen(stack, mouseX, mouseY, partialTicks) { - + for (let i in this.buttonList) { + let button = this.buttonList[i]; + button.render(stack, mouseX, mouseY, partialTicks); + } } keyTyped(code) { @@ -18,4 +33,14 @@ window.GuiScreen = class extends Gui { return false; } + mouseClicked(mouseX, mouseY, mouseButton) { + for (let i in this.buttonList) { + let button = this.buttonList[i]; + + if (button.isMouseOver(mouseX, mouseY)) { + button.mouseClicked(mouseX, mouseY, mouseButton); + } + } + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/gui/IngameOverlay.js b/src/js/net/minecraft/client/gui/IngameOverlay.js index 6344c60..723ef3a 100644 --- a/src/js/net/minecraft/client/gui/IngameOverlay.js +++ b/src/js/net/minecraft/client/gui/IngameOverlay.js @@ -4,7 +4,7 @@ window.IngameOverlay = class extends Gui { super(); this.window = window; - this.textureCrosshair = this.loadTexture("icons.png"); + this.textureCrosshair = Gui.loadTexture("icons.png"); } render(stack, mouseX, mouseY, partialTicks) { diff --git a/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js b/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js index fe80bac..fdab5eb 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js +++ b/src/js/net/minecraft/client/gui/screens/GuiIngameMenu.js @@ -4,8 +4,23 @@ window.GuiIngameMenu = class extends GuiScreen { super(); } - drawScreen(stack, mouseX, mouseY, partialTicks) { + init() { + super.init(); + let scope = this; + this.buttonList.push(new GuiButton("Back to game", this.width / 2 - 100 * 3, this.height / 2 - 50 * 3, 200 * 3, 20 * 3, function () { + scope.minecraft.displayScreen(null); + })); + } + + drawScreen(stack, mouseX, mouseY, partialTicks) { + // Background + this.drawRect(stack, 0, 0, this.width, this.height, 'black', 0.6); + + // Title + this.drawCenteredString(stack, "Game paused", this.width / 2, 100); + + 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 index 4007f75..42e9b7a 100644 --- a/src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js +++ b/src/js/net/minecraft/client/gui/screens/GuiLoadingScreen.js @@ -3,7 +3,7 @@ window.GuiLoadingScreen = class extends GuiScreen { constructor() { super(); - this.textureBackground = this.loadTexture("background.png"); + this.textureBackground = Gui.loadTexture("background.png"); } drawScreen(stack, mouseX, mouseY, partialTicks) { @@ -35,6 +35,8 @@ window.GuiLoadingScreen = class extends GuiScreen { this.height / 2 + progressHeight / 2, '#80ff80', ); + + super.drawScreen(stack, mouseX, mouseY, partialTicks); } setTitle(title) { diff --git a/src/js/net/minecraft/client/gui/widgets/GuiButton.js b/src/js/net/minecraft/client/gui/widgets/GuiButton.js new file mode 100644 index 0000000..952e373 --- /dev/null +++ b/src/js/net/minecraft/client/gui/widgets/GuiButton.js @@ -0,0 +1,30 @@ +window.GuiButton = class extends Gui { + + static textureGui = Gui.loadTexture("gui.png"); + + constructor(string, x, y, width, height, callback) { + super(); + + this.string = string; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.callback = callback; + } + + render(stack, mouseX, mouseY, partialTicks) { + let mouseOver = this.isMouseOver(mouseX, mouseY); + this.drawSprite(stack, GuiButton.textureGui, 0, mouseOver ? 40 : 20, 200, 20, this.x, this.y, this.width, this.height); + this.drawCenteredString(stack, this.string, this.x + this.width / 2, this.y + this.height / 2 + 17); + } + + mouseClicked(mouseX, mouseY, mouseButton) { + this.callback(); + } + + isMouseOver(mouseX, mouseY) { + return mouseX > this.x && mouseX < this.x + this.width && mouseY > this.y && mouseY < this.y + this.height; + } + +} \ No newline at end of file diff --git a/src/js/net/minecraft/client/world/World.js b/src/js/net/minecraft/client/world/World.js index 7d8b3cf..4c64e1c 100644 --- a/src/js/net/minecraft/client/world/World.js +++ b/src/js/net/minecraft/client/world/World.js @@ -13,6 +13,16 @@ window.World = class { // Load world this.generator = new WorldGenerator(this, Date.now() % 100000); + + // Update lights async + let scope = this; + setInterval(function () { + let i = 1000; + while (scope.lightUpdateQueue.length >= 10 && i > 0) { + i--; + scope.lightUpdateQueue.shift().updateBlockLightning(scope); + } + }, 1); } onTick() { @@ -83,22 +93,7 @@ window.World = class { updateLights() { 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 { + if (this.lightUpdateQueue.length < 10) { // Update lights in queue let i = 10; while (scope.lightUpdateQueue.length > 0) { diff --git a/src/resources/gui.png b/src/resources/gui.png new file mode 100644 index 0000000000000000000000000000000000000000..973dd0d0298898a87cf10b4172136594beca878f GIT binary patch literal 8645 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 literal 0 HcmV?d00001 diff --git a/src/resources/terrain.png b/src/resources/terrain.png index e0e796fcb519e0097734a61ade632fe39a5708f5..20e058ba5106219d0a4c92fbb6fcb301b46c07b4 100644 GIT binary patch literal 7547 zcmeI1XH*l+n#U7*5krZJ3JD4dNRuud0SR0>7O>EyDZPf!i%}FXp(7oI7hVla2Xot zSpopSpIsn;jpb+a$nSR-065$>)6J45&+sijp{e7uRBwGa zdlgG7JzwR#e&hWE^_v{7=+rD{zUAF4e3k3>fcLga_lczujpJI8BQITld$P{<-azn5 z^Svv5$m4PYY!#2Cor-RE7gy>Q>Gl=1;EGhq*BQchS6n4g8G)SdmJG09yoG|zwc9YG zt~d*VI{fzp0m2)w9ev}Y(~!srcs=xll)K?@-)7JjtbVV}W<#N;V6?5;e~KXYs9}^`&+gTP4p) zk!JW-a%y&f_}Cbn6*#*XxW6($Jae?%CTpk^USaU3S;O=k&PAtzF7~>Q7)>+QZwMiX2MhT7v~EX#vr|OnE08zZkA(gkZ;|J2VfKlnlu! z6S4UVw8mr-VHV}_ULI(koGfrgXn@(q<%Uli9XklBjiHpTiqHcKdyaZFGfT<(<}#ld-bi zDIDimf~^v^G>!%GsmD5RDNBc!#UJsH3j!FkS^8FK>;6G;l$G4ekp&ykFUP^jLnZoJ zZTt5FLYl=_P(F9y?l+{HC35WJ)Ksgb)ThCbcl50gh^uj!Q6vM!^!9<^g2T$J!;0z{ zldkUQ>Dyn+4PdUhVer6@3e#T>KaLDFjGhg5?1$`!jI9;5mcRA=7_1>RFc3&suYEu^ z3h<1jU~bW9giByWRaI5>IOsSVlQGlXyLT-uEgwI7+tTvL&CP9-Y_HSaddn`~p_VwJ z_YjFd55^yf$$>>}M@`W+5LN&Aw?Y!DsKl-JDMfxXetb(<@}_CNr0DoSTK`?6WvRl} z`|{4!nGDyA*>Ys^L}Are`|FnZHkZsbwce9g%X9bx$8kM@yZd`IGb%-~nic!9!!Fh2 zV|U*dq^pw&ft$4b>e1Av>aS$p(HTzTx0eCe?uqne_GQXl+52c|r+(`yI&2UQ2UC^N z%e_Hn%h({((lqb!@}wivl?UNF0d0pEx|_vO==3w8b|!8x!BGkwh}ofU(0H3XIH;Q% zxpdaq>ESCCe==7dPQnyHJ`pn|6Q*b zxj6FpYV<6PAsK@STWgPItScBE=3%&~>{T-^hF}6{g5n^#(C2nmR^zQs?Y&%S5svAb z-DYu`fkWZ0#cronCc984QahwXiuT4s9_XYOr^!(miE1450D+9$L5>G73+34l z^1}3+jl(stNmbcD3O5QT&;}2CY@aIT-zwu_ffZFY-cud8Gc;wVO*qN`y={=~E1chh zgfcvT{+xKSyU+<22SD8;CHYPZs)`&Q9x5?i7cWS8mlzYM6en2DUv6<=o$pPf@nTi; zMK+|(YV!|IF$e60xa`jwAP)g0U0ZJ{`OakcbFw4n>K}JL9eiNhxRKJ!M^R5Xq8pTvFDiuVrSs zNT#@M5n_)`#ZvYA*-#ZCdzJpw6>VZ^2mEoA`M0&rn*iioS<#+f_#g#B+%h>awobG)+Ea7$?r){hg@q_R>KNOzLqbW_!n*wr%z| zTf)jCK1uE7sOT;sumR$>V407_8s2K*-Ak^^0i*ymAXo~OQ7eNHyA9KjG3wTMs?~E< zXzak6fyte0Pl-MHwD{5U#(X$8%TE4%*BvP(Iy5f0{X0-@_lR*PfVdS@91WzaYwJK` zJ-8=uSzZ`g?Vctlds9dNixSbeN7+VWtn_FvZUDnyN~)a2{a_O<${a+Se6H!GTCB7o zDns5Q(9^8=Rje6pr{8y7~ z>3;@7iw#4;N5>*qbm5S)$Ao<+V1sUd1QlgwW07R^xfVsfE?CfRF(C#=0+ePppM;Yy zbfL@8?k#^@IMQxtv#!%_b7?wS`Sx^%49rlL#7J<@I}F%WBTBzX=Gv=;c9ilEoeJv1 z@B}7&SVdLcHWE>$9YG0sMIn&_2@7}~GKUu1%O7_aMLt~X^V(z% z1x!qY?(RTS->&4h(wcj_=UTgm{QTpe|SN;9q%Y;!q8+?RL%UEr%()r^M2&^Zxr+fwjXbhRk+;WC!k zCaf554ES2H4^5!2(V#il+DqIyyiBktYhHT>u?Gr|PUvlz1NW^UD=X-+ z45R1u1IdGPUok==`k9f>=#D-j0OL!JL0VTu{kpZ(3+1b5$~Kx8+DPgbU=iy{h3yEW z-n|SPx})9v;@sF9_JVs^4=UQUT=Xf6g!Q`uhnb3zQxWTH?Xp5dfNfHDdh5uOma(bq z==uln!;`;oZOb1Zh5#$*hm>x}vV+f@!D9h$qj0i7rk*G^KnrVp3hE!G`uYYmCH|9?dgS;r%$k7 z3h$GjVTL47#C#B#ExJO-Z1S41_n1mfx(*FuWD}CUR!nC71pUnx8y$ z6q>_JQTo>EqD3!9{mS)asg%sUnTyC9yvW%{m^;@jjT8H z(F8-et;$VHQ4L`-p?hlEw(fDN$D=f-IEu={5Sovlp6v(x@zUdH6+dr4ZP)o61wX#^1UaQ6+rw z8Dc_oV*aB^_O%SMg^h`=gjh zxjFbz4703dwOo~%xtnGrU9T(`Y$>WGD%vj$i*3-Cb*zWpjFLu=+xI~8nM)YgXve2O zOb#jlO+?>L2O63xL*K~Ay}lMyosTS=n}uFCio#L12S;PfB_RYuZ+T`ES3A6V+ZzPJ zxmDlR_JA*maib}J$j+~Qg*OZE#{jMyF@(WqH202POnXc^KumIqN(e*LmE+rVoZJ_3@46ICt!Fn$IEPKyCjA%2EO5l37wlscIer^9b9cZjLMjiD8Z86 zHIAuybHHJfB2!pUSsve>i3JpwDV?33km0{<6gp5CU#b~#jUyPKfZPcikM$m>u4o_=wP7ICA+20k3#?Z5 zllP(x`g_7c(rGd^xhFN^^VQG&mo2*C1Z*-Flm_S9KuK+YT^B`a3fNCUuvcKX;nrNAu-nqN4h13=R1dP3+aiKpb~$zL%;=#b;$ z4J|Sn*SEi7H?LuJoHGxFFvV5d5pG6jTg;tRSE619QS=rmP#fqBotP0*ap@&2nlTQC~@jcm4x5rVNn+E#_P*k|#(9l=F(BPCP@R_MM z?$E@wM-l0Two+$8I_h{ZJ-*N`5vDGQybLP=jU9G0pnsZ8mErOm7W0FK?pEv5LIOjt zK~APA@}%mbh=Ei1eEF#e;2L6EV07RdcJKSBNqvMN+{HNUwb9jyLd`I^n@ybHR%pLf zF*8bdf9`I`jQ(xo>BW-S|$OxeDMo%azgEXgDTemn61vw#(4a?Omza zMPcWD{mFIU=kXYe2}B?0;){v(Sadnlv)WO8{p4JMT>)*non9Vk=l#%gwJ!QGMnf7D zpe|$x97h(8%{; zdVhXtp|FB)9h%?)4a#T2^ztaJdFb9byF8%w>|U6jtuhWEw1d#RT%PR;NDNYkCXEls z1A5hdj@ei_4_Fe!!IlE|PXP$1RbfI?Fbg2KXP+l{Mx8OLWs&r<#p`cdhNc0C`_cIa z)BmG{Upt{g0Jjbud>Q`rr|?U{ufvQ4MZG(zxB>i^UBrKv@XHn$R&9%L>zseO7ybtc z|K-fpImUwDH6=~|S$6ziNca^T`#V7MJJ7SD|KN!DzexBMpQIyz*auKN-#;cO|0W5) z5J3qAfWOCfvHx9M`1>UMqSU|f^4D4YZ@m1~jP-B4{PpxtKR4Awe6h|3bo%+J3NXB7 Ks#m6CAM+n}9q>5- literal 6686 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 diff --git a/src/start.js b/src/start.js index 84a2ccc..2454473 100644 --- a/src/start.js +++ b/src/start.js @@ -61,6 +61,7 @@ loadScripts([ "src/js/net/minecraft/util/Keyboard.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", "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", diff --git a/style.css b/style.css index 2ce76c1..cba8926 100644 --- a/style.css +++ b/style.css @@ -37,6 +37,7 @@ body { /* Font */ font-size: 25px; font-family: "Minecraftia", sans-serif; + text-shadow: 2px 2px #000000; color: white; }