diff --git a/README.md b/README.md index fd03953..e270dc5 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ # WebDisplays for Minecraft 1.19.2 -This is a fork of the Web Displays mod from 1.12, updated to work on 1.19, and with some bug fixes and reworking. +This is a fork of the Web Displays mod from 1.12, updated to work in newer versions, and with some bug fixes and reworking. ### Wiki * The Wiki that details all blocks/items can be found on my website https://montoyo.net/wdwiki/ ### Delayed things * Plugin API -* The Shop -* CC Interface, if CC gets updated... +* The Shop (what) * Center camera to screen when using keyboard * minePad management: check GuiContainer.draggedStack for minePad * In-game command to add/remove blacklisted domains -* Config: RPMP (Real pixels per Minecraft pixels) -* Disable miniserv in solo +* Config: RPMP (Real pixels per Minecraft pixels) (what) +* CC Interface (for when it's actually possible, since the screens are client only currently, but a config option is planned to change that) +* Redstone controls (same reason as CC interface) +* Redo minisrv logic? diff --git a/libs/mcef-2.x.jar b/libs/mcef-2.x.jar index 6e2a0fe..f4316ec 100644 Binary files a/libs/mcef-2.x.jar and b/libs/mcef-2.x.jar differ diff --git a/src/main/java/net/montoyo/wd/client/ClientProxy.java b/src/main/java/net/montoyo/wd/client/ClientProxy.java index b4f3705..56ee004 100644 --- a/src/main/java/net/montoyo/wd/client/ClientProxy.java +++ b/src/main/java/net/montoyo/wd/client/ClientProxy.java @@ -85,6 +85,7 @@ import org.cef.CefSettings; import org.cef.browser.CefBrowser; import org.cef.browser.CefFrame; import org.cef.handler.CefDisplayHandler; +import org.cef.network.CefRequest; import org.joml.Vector3d; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -138,12 +139,11 @@ public class ClientProxy extends SharedProxy implements CefDisplayHandler/*, IJS return; if (!LaserPointerRenderer.isOn()) { - RenderSystem.setShaderTexture(0, new ResourceLocation( - "webdisplays:textures/gui/cursors.png" - )); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); - -// blit(poseStack, (screenWidth - 15) / 2, (screenHeight - 15) / 2, 240, 240, 15, 15, offset); + + poseStack.blit(new ResourceLocation( + "webdisplays:textures/gui/cursors.png" + ), (screenWidth - 15) / 2, (screenHeight - 15) / 2, offset, 240, 240, 15, 15, 256, 256); ci.cancel(); return; } @@ -154,9 +154,16 @@ public class ClientProxy extends SharedProxy implements CefDisplayHandler/*, IJS BlockPos bpos = result.getBlockPos(); - if (result.getType() != HitResult.Type.BLOCK || mc.level.getBlockState(bpos).getBlock() != BlockInit.blockScreen.get()) + if (result.getType() != HitResult.Type.BLOCK || mc.level.getBlockState(bpos).getBlock() != BlockInit.blockScreen.get()) { + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + + poseStack.blit(new ResourceLocation( + "webdisplays:textures/gui/cursors.png" + ), (screenWidth - 15) / 2, (screenHeight - 15) / 2, offset, 240, 240, 15, 15, 256, 256); + ci.cancel(); return; - + } + Vector3i pos = new Vector3i(result.getBlockPos()); BlockSide side = BlockSide.values()[result.getDirection().ordinal()]; @@ -166,19 +173,17 @@ public class ClientProxy extends SharedProxy implements CefDisplayHandler/*, IJS TileEntityScreen.Screen sc = te.getScreen(side); if (sc == null) return; -// if (sc.mouseType == 1) return; - + int coordX = sc.mouseType * 15; int coordY = coordX / 256; coordX -= coordY * 256; - RenderSystem.setShaderTexture(0, new ResourceLocation( - "webdisplays:textures/gui/cursors.png" - )); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE_MINUS_DST_COLOR, GlStateManager.DestFactor.ONE_MINUS_SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); - -// blit(poseStack, (screenWidth - 15) / 2, (screenHeight - 15) / 2, coordX, coordY, 15, 15, offset); - + + poseStack.blit(new ResourceLocation( + "webdisplays:textures/gui/cursors.png" + ), (screenWidth - 15) / 2, (screenHeight - 15) / 2, offset, coordX, coordY, 15, 15, 256, 256); + ci.cancel(); } @@ -258,16 +263,21 @@ public class ClientProxy extends SharedProxy implements CefDisplayHandler/*, IJS @Override public void onCefInit(/*CefInitEvent event*/) { MinecraftForge.EVENT_BUS.register(this); -// if (mcef != null) -// mcef.registerScheme("wd", WDScheme.class, true, false, false, true, true, false, false); + + if (!MCEF.isInitialized()) return; + + MCEF.getApp().getHandle().registerSchemeHandlerFactory( + "webdisplays", "", + (browser, frame, url, request) -> { + // TODO: check if it's a webdisplays browser? + return new WDScheme(request.getURL()); + } + ); // jsDispatcher = new JSQueryDispatcher(this); minePadRenderer = new MinePadRenderer(); laserPointerRenderer = new LaserPointerRenderer(); -// if (mcef == null) -// throw new RuntimeException("MCEF is missing"); - MCEF.getClient().addDisplayHandler(this); // mcef.registerJSQueryHandler(this); findAdvancementToProgressField(); diff --git a/src/main/java/net/montoyo/wd/client/WDScheme.java b/src/main/java/net/montoyo/wd/client/WDScheme.java index 7e21582..40caf0f 100644 --- a/src/main/java/net/montoyo/wd/client/WDScheme.java +++ b/src/main/java/net/montoyo/wd/client/WDScheme.java @@ -1,149 +1,196 @@ -///* -// * Copyright (C) 2018 BARBOTIN Nicolas -// */ -// -//package net.montoyo.wd.client; -// -//import net.montoyo.mcef.api.IScheme; -//import net.montoyo.mcef.api.ISchemeResponseData; -//import net.montoyo.mcef.api.ISchemeResponseHeaders; -//import net.montoyo.mcef.api.SchemePreResponse; -//import net.montoyo.wd.WebDisplays; -//import net.montoyo.wd.miniserv.Constants; -//import net.montoyo.wd.miniserv.client.Client; -//import net.montoyo.wd.miniserv.client.ClientTaskGetFile; -//import net.montoyo.wd.utilities.Log; -//import net.montoyo.wd.utilities.Util; -// -//import java.io.UnsupportedEncodingException; -//import java.net.URLDecoder; -//import java.util.UUID; -// -//public class WDScheme implements IScheme { -// -// private static final String ERROR_PAGE = "

%d %s


Miniserv powered by WebDisplays"; -// private ClientTaskGetFile task; -// private boolean isErrorPage; -// -// @Override -// public SchemePreResponse processRequest(String url) { -// url = url.substring("wd://".length()); -// -// int pos = url.indexOf('/'); -// if(pos < 0) -// return SchemePreResponse.NOT_HANDLED; -// -// String uuidStr = url.substring(0, pos); -// String fileStr = url.substring(pos + 1); -// -// try { -// fileStr = URLDecoder.decode(fileStr, "UTF-8"); -// } catch(UnsupportedEncodingException ex) { -// Log.warningEx("UTF-8 isn't supported... yeah... and I'm a billionaire...", ex); -// } -// -// if(uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr)) -// return SchemePreResponse.NOT_HANDLED; -// -// UUID uuid; -// try { -// uuid = UUID.fromString(uuidStr); -// } catch(IllegalArgumentException ex) { -// return SchemePreResponse.NOT_HANDLED; //Invalid UUID -// } -// -// task = new ClientTaskGetFile(uuid, fileStr); -// return Client.getInstance().addTask(task) ? SchemePreResponse.HANDLED_CONTINUE : SchemePreResponse.NOT_HANDLED; -// } -// -// @Override -// public void getResponseHeaders(ISchemeResponseHeaders resp) { -// Log.info("Waiting for response..."); -// int status = task.waitForResponse(); -// Log.info("Got response %d", status); -// -// if(status == 0) { -// //OK -// int extPos = task.getFileName().lastIndexOf('.'); -// if(extPos >= 0) { -// String mime = ((ClientProxy) WebDisplays.PROXY).getMCEF().mimeTypeFromExtension(task.getFileName().substring(extPos + 1)); -// -// if(mime != null) -// resp.setMimeType(mime); -// } -// -// resp.setStatus(200); -// resp.setStatusText("OK"); -// resp.setResponseLength(-1); -// return; -// } -// -// int errCode; -// String errStr; -// -// if(status == Constants.GETF_STATUS_NOT_FOUND) { -// errCode = 404; -// errStr = "Not Found"; -// } else { -// errCode = 500; -// errStr = "Internal Server Error"; -// } -// -// resp.setStatus(errCode); -// resp.setStatusText(errStr); -// -// try { -// dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes("UTF-8"); -// dataOffset = 0; -// amountToWrite = dataToWrite.length; -// isErrorPage = true; -// resp.setResponseLength(amountToWrite); -// } catch(UnsupportedEncodingException ex) { -// resp.setResponseLength(0); -// } -// } -// -// private byte[] dataToWrite; -// private int dataOffset; -// private int amountToWrite; -// -// @Override -// public boolean readResponse(ISchemeResponseData data) { -// if(dataToWrite == null) { -// if(isErrorPage) { +/* + * Copyright (C) 2018 BARBOTIN Nicolas + */ + +package net.montoyo.wd.client; + +import net.montoyo.wd.miniserv.Constants; +import net.montoyo.wd.miniserv.client.Client; +import net.montoyo.wd.miniserv.client.ClientTaskGetFile; +import net.montoyo.wd.utilities.Log; +import net.montoyo.wd.utilities.Util; +import org.cef.callback.CefCallback; +import org.cef.handler.CefResourceHandler; +import org.cef.misc.IntRef; +import org.cef.misc.StringRef; +import org.cef.network.CefRequest; +import org.cef.network.CefResponse; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.UUID; + +public class WDScheme implements CefResourceHandler { + + private static final String ERROR_PAGE = "

%d %s


Miniserv powered by WebDisplays"; + private ClientTaskGetFile task; + private boolean isErrorPage; + + String url; + + public WDScheme(String url) { + this.url = url; + } + + @Override + public boolean processRequest(CefRequest cefRequest, CefCallback cefCallback) { + url = cefRequest.getURL(); + + int pos = url.indexOf('/'); + if(pos < 0) + return false; + + String uuidStr = url.substring(0, pos); + String fileStr = url.substring(pos + 1); + + try { + fileStr = URLDecoder.decode(fileStr, "UTF-8"); + } catch(UnsupportedEncodingException ex) { + Log.warningEx("UTF-8 isn't supported... yeah... and I'm a billionaire...", ex); + } + + if(uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr)) + return false; + + UUID uuid; + try { + uuid = UUID.fromString(uuidStr); + } catch(IllegalArgumentException ex) { + return false; //Invalid UUID + } + + task = new ClientTaskGetFile(uuid, fileStr); + return Client.getInstance().addTask(task) ? true : false; + } + + @Override + public void getResponseHeaders(CefResponse cefResponse, IntRef intRef, StringRef stringRef) { + Log.info("Waiting for response..."); + int status = task.waitForResponse(); + Log.info("Got response %d", status); + + if(status == 0) { + //OK + int extPos = task.getFileName().lastIndexOf('.'); + if(extPos >= 0) { + String mime = mapMime(task.getFileName().substring(extPos + 1)); + + if(mime != null) + cefResponse.setMimeType(mime); + } + + cefResponse.setStatus(200); + cefResponse.setStatusText("OK"); + cefResponse.setHeaderByName("content-length", "" + -1, true); + return; + } + + int errCode; + String errStr; + + if(status == Constants.GETF_STATUS_NOT_FOUND) { + errCode = 404; + errStr = "Not Found"; + } else { + errCode = 500; + errStr = "Internal Server Error"; + } + + cefResponse.setStatus(errCode); + cefResponse.setStatusText(errStr); + + try { + dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes("UTF-8"); + dataOffset = 0; + amountToWrite = dataToWrite.length; + isErrorPage = true; + cefResponse.setHeaderByName("content-length", "" + amountToWrite, true); + } catch(UnsupportedEncodingException ex) { + cefResponse.setHeaderByName("content-length", "" + 0, true); +// cefResponse.setResponseLength(0); + } + } + + private byte[] dataToWrite; + private int dataOffset; + private int amountToWrite; + + @Override + public boolean readResponse(byte[] bytes, int i, IntRef intRef, CefCallback cefCallback) { + if(dataToWrite == null) { + if(isErrorPage) { // data.setAmountRead(0); -// return false; -// } -// -// dataToWrite = task.waitForData(); -// dataOffset = 3; //packet ID + size -// amountToWrite = task.getDataLength(); -// -// if(amountToWrite <= 0) { -// dataToWrite = null; + return false; + } + + dataToWrite = task.waitForData(); + dataOffset = 3; //packet ID + size + amountToWrite = task.getDataLength(); + + if(amountToWrite <= 0) { + dataToWrite = null; // data.setAmountRead(0); -// return false; -// } -// } -// + return false; + } + } + // int toWrite = data.getBytesToRead(); // if(toWrite > amountToWrite) // toWrite = amountToWrite; -// + // System.arraycopy(dataToWrite, dataOffset, data.getDataArray(), 0, toWrite); // data.setAmountRead(toWrite); -// + // dataOffset += toWrite; // amountToWrite -= toWrite; -// -// if(amountToWrite <= 0) { -// if(!isErrorPage) -// task.nextData(); -// -// dataToWrite = null; -// } -// -// return true; -// } -// -//} + + if(amountToWrite <= 0) { + if(!isErrorPage) + task.nextData(); + + dataToWrite = null; + } + + return true; + } + + @Override + public void cancel() { + } + + public static String mapMime(String ext) { + switch (ext) { + case "htm": + case "html": + return "text/html"; + + case "css": + return "text/css"; + + case "js": + return "text/javascript"; + + case "png": + return "image/png"; + + case "jpg": + case "jpeg": + return "image/jpeg"; + + case "gif": + return "image/gif"; + + case "svg": + return "image/svg+xml"; + + case "xml": + return "text/xml"; + + case "txt": + return "text/plain"; + + default: + return null; + } + } +} diff --git a/src/main/java/net/montoyo/wd/client/gui/GuiServer.java b/src/main/java/net/montoyo/wd/client/gui/GuiServer.java index 6f6c23d..4a2e71c 100644 --- a/src/main/java/net/montoyo/wd/client/gui/GuiServer.java +++ b/src/main/java/net/montoyo/wd/client/gui/GuiServer.java @@ -96,8 +96,8 @@ public class GuiServer extends WDScreen { } @Override - public void render(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) { - super.render(poseStack, mouseX, mouseY, ptt); + public void render(GuiGraphics graphics, int mouseX, int mouseY, float ptt) { + super.render(graphics, mouseX, mouseY, ptt); int x = (width - 256) / 2; int y = (height - 176) / 2; @@ -105,27 +105,27 @@ public class GuiServer extends WDScreen { // RenderSystem.enableTexture(); RenderSystem.setShaderTexture(0, BG_IMAGE); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); -// blit(poseStack, x, y, 0, 0, 256, 176); - + graphics.blit(BG_IMAGE, x, y, 0, 0, 256, 256); + x += 18; y += 18; for (int i = 0; i < lines.size(); i++) { if (selectedLine == i) { drawWhiteQuad(x - 1, y - 2, font.width(lines.get(i)) + 1, 12); - poseStack.drawString(Minecraft.getInstance().font, lines.get(i), x, y, 0xFF129700, false); + graphics.drawString(Minecraft.getInstance().font, lines.get(i), x, y, 0xFF129700, false); } else - poseStack.drawString(Minecraft.getInstance().font, lines.get(i), x, y, 0xFFFFFFFF, false); + graphics.drawString(Minecraft.getInstance().font, lines.get(i), x, y, 0xFFFFFFFF, false); y += 12; } if (!promptLocked) { if (queue.isEmpty()) { - x = poseStack.drawString(Minecraft.getInstance().font, userPrompt, x, y, 0xFFFFFFFF, false); - x = poseStack.drawString(Minecraft.getInstance().font, prompt, x, y, 0xFFFFFFFF, false); + x = graphics.drawString(Minecraft.getInstance().font, userPrompt, x, y, 0xFFFFFFFF, false); + x = graphics.drawString(Minecraft.getInstance().font, prompt, x, y, 0xFFFFFFFF, false); } else { - x = poseStack.drawString(Minecraft.getInstance().font, tr("press_for_more"), x, y, 0xFFFFFFFF, false); + x = graphics.drawString(Minecraft.getInstance().font, tr("press_for_more"), x, y, 0xFFFFFFFF, false); } } @@ -137,7 +137,7 @@ public class GuiServer extends WDScreen { RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.setShaderTexture(0, FG_IMAGE); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); -// blit(poseStack,(width - 256) / 2, (height - 176) / 2, 0, 0, 256, 176); +// blit(graphics,(width - 256) / 2, (height - 176) / 2, 0, 0, 256, 176); } private void drawWhiteQuad(int x, int y, int w, int h) { diff --git a/src/main/java/net/montoyo/wd/client/gui/RenderRecipe.java b/src/main/java/net/montoyo/wd/client/gui/RenderRecipe.java index f06fc89..8ff2535 100644 --- a/src/main/java/net/montoyo/wd/client/gui/RenderRecipe.java +++ b/src/main/java/net/montoyo/wd/client/gui/RenderRecipe.java @@ -100,15 +100,15 @@ public class RenderRecipe extends Screen { int x = this.x + 30 + sx * 18; int y = this.y + 17 + sy * 18; -// renderItem.renderAndDecorateItem(minecraft.player, is, x, y, 0); -// renderItem.renderGuiItemDecorations(font, is, x, y, null); + context.renderItem(is, x, y); + context.renderItemDecorations(font, is, x, y); } } } if(recipeResult != null) { -// renderItem.renderAndDecorateItem(minecraft.player, recipeResult, x + 124, y + 35, 0); -// renderItem.renderGuiItemDecorations(font, recipeResult, x + 124, y + 35, null); + context.renderItem(recipeResult, x, y); + context.renderItemDecorations(font, recipeResult, x, y); } // GlStateManager.enableLighting(); diff --git a/src/main/java/net/montoyo/wd/client/gui/WDScreen.java b/src/main/java/net/montoyo/wd/client/gui/WDScreen.java index 7c6842a..1a1740e 100644 --- a/src/main/java/net/montoyo/wd/client/gui/WDScreen.java +++ b/src/main/java/net/montoyo/wd/client/gui/WDScreen.java @@ -7,6 +7,7 @@ package net.montoyo.wd.client.gui; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -116,6 +117,8 @@ public abstract class WDScreen extends Screen { if(defaultBackground) renderBackground(poseStack); + RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f); + for(Control ctrl: controls) ctrl.draw(poseStack, mouseX, mouseY, ptt); @@ -137,9 +140,20 @@ public abstract class WDScreen extends Screen { public boolean mouseClicked(double mouseX, double mouseY, int button) { boolean clicked = false; + Control clickedEl = null; for(Control ctrl: controls) { clicked = ctrl.mouseClicked(mouseX, mouseY, button); - if (clicked) break; // don't assume the compiler will optimize stuff + if (clicked) { + clickedEl = ctrl; + break; // don't assume the compiler will optimize stuff + } + } + + if (clicked) { + for (Control control : controls) { + if (control != clickedEl) + control.unfocus(); + } } return clicked; diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/CheckBox.java b/src/main/java/net/montoyo/wd/client/gui/controls/CheckBox.java index 98aefc1..0d14ca1 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/CheckBox.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/CheckBox.java @@ -9,6 +9,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; @@ -81,12 +82,11 @@ public class CheckBox extends BasicControl { if(visible) { // GlStateManager.disableAlpha(); poseStack.pose().pushPose(); - RenderSystem.setShaderTexture(2, checked ? texChecked : texUnchecked); - RenderSystem.bindTexture(2); RenderSystem.enableBlend(); - fillTexturedRect(poseStack.pose(), x, y, WIDTH, HEIGHT, 0.0, 0.0, 1.0, 1.0); + poseStack.blit( + checked ? texChecked : texUnchecked, x, y, 0, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT + ); RenderSystem.disableBlend(); - RenderSystem.bindTexture(-1); poseStack.pose().popPose(); boolean inside = (!disabled && mouseX >= x && mouseX <= x + WIDTH + 2 + labelW && mouseY >= y && mouseY < y + HEIGHT); diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/Container.java b/src/main/java/net/montoyo/wd/client/gui/controls/Container.java index 488f284..e6b33c7 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/Container.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/Container.java @@ -189,4 +189,10 @@ public abstract class Container extends BasicControl { return null; } + @Override + public void unfocus() { + for (Control control : childs) { + control.unfocus(); + } + } } diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/Control.java b/src/main/java/net/montoyo/wd/client/gui/controls/Control.java index 589a415..1d973a1 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/Control.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/Control.java @@ -11,6 +11,10 @@ import com.mojang.blaze3d.vertex.*; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.resources.language.I18n; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; @@ -20,6 +24,9 @@ import net.montoyo.wd.client.gui.loading.JsonOWrapper; import net.montoyo.wd.utilities.Bounds; import org.joml.Matrix4f; +import java.util.Arrays; + +import static com.mojang.math.Axis.XP; import static org.lwjgl.opengl.GL11.*; @OnlyIn(Dist.CLIENT) @@ -74,6 +81,9 @@ public abstract class Control { return false; } + public void unfocus() { + } + public boolean mouseReleased(double mouseX, double mouseY, int state) { return false; } @@ -109,7 +119,7 @@ public abstract class Control { public abstract int getHeight(); public abstract void setPos(int x, int y); - public void fillRect(int x, double y, int w, int h, int color) { + public void fillRect(MultiBufferSource.BufferSource source, int x, double y, int w, int h, int color) { double x1 = (double) x; double y1 = (double) y; double x2 = (double) (x + w); @@ -119,34 +129,38 @@ public abstract class Control { int g = (color >> 8 ) & 0xFF; int b = color & 0xFF; - RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f); + float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4); + RenderSystem.setShaderColor(1, 1, 1, 1f); // RenderSystem.disableTexture(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); - vBuffer.vertex(x1, y2, 0.0).endVertex(); - vBuffer.vertex(x2, y2, 0.0).endVertex(); - vBuffer.vertex(x2, y1, 0.0).endVertex(); - vBuffer.vertex(x1, y1, 0.0).endVertex(); - tessellator.end(); + VertexConsumer consumer = source.getBuffer(RenderType.gui()); + consumer.vertex(x1, y2, 0.0).color(r, g, b, a).endVertex(); + consumer.vertex(x2, y2, 0.0).color(r, g, b, a).endVertex(); + consumer.vertex(x2, y1, 0.0).color(r, g, b, a).endVertex(); + consumer.vertex(x1, y1, 0.0).color(r, g, b, a).endVertex(); + + RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]); RenderSystem.disableBlend(); // RenderSystem.enableTexture(); } public void fillTexturedRect(PoseStack poseStack, int x, int y, int w, int h, double u1, double v1, double u2, double v2) { - double x1 = (double) x; - double y1 = (double) y; - double x2 = (double) (x + w); - double y2 = (double) (y + h); + float x1 = x; + float y1 = y; + float x2 = (x + w); + float y2 = (y + h); - vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); - vBuffer.vertex(x1, y2, 0.0).uv((float) u1, (float) v2).color(255, 255, 255, 255).endVertex(); - vBuffer.vertex(x2, y2, 0.0).uv((float) u2, (float) v2).color(255, 255, 255, 255).endVertex(); - vBuffer.vertex(x2, y1, 0.0).uv((float) u2, (float) v1).color(255, 255, 255, 255).endVertex(); - vBuffer.vertex(x1, y1, 0.0).uv((float) u1, (float) v1).color(255, 255, 255, 255).endVertex(); - tessellator.end(); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + Matrix4f p = poseStack.last().pose(); + vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + vBuffer.vertex(p, x1, y2, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v2).endVertex(); + vBuffer.vertex(p, x2, y2, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v2).endVertex(); + vBuffer.vertex(p, x2, y1, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v1).endVertex(); + vBuffer.vertex(p, x1, y1, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v1).endVertex(); + BufferUploader.drawWithShader(vBuffer.end()); } public static void blend(boolean enable) { @@ -178,6 +192,7 @@ public abstract class Control { int g = (color >> 8 ) & 0xFF; int b = color & 0xFF; + float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4); RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f); // RenderSystem.enableTexture(); RenderSystem.enableBlend(); @@ -209,13 +224,15 @@ public abstract class Control { vBuffer.vertex(x2 - sz, y1, 0.0).endVertex(); tessellator.end(); + RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]); + RenderSystem.disableBlend(); // RenderSystem.enableTexture(); } public GuiGraphics beginFramebuffer(RenderTarget fbo, float vpW, float vpH) { GuiGraphics tmpGraphics = new GuiGraphics(Minecraft.getInstance(), Minecraft.getInstance().renderBuffers().bufferSource()); - + fbo.bindWrite(true); RenderSystem.backupProjectionMatrix(); @@ -226,7 +243,10 @@ public abstract class Control { PoseStack poseStack = tmpGraphics.pose(); poseStack.pushPose(); poseStack.setIdentity(); -// poseStack.mulPose(Vector3f.XP.rotationDegrees(180.0f)); + poseStack.mulPose(XP.rotationDegrees(180.0f)); + RenderSystem.getModelViewStack().pushPose(); + RenderSystem.getModelViewStack().last().pose().set(poseStack.last().pose()); + RenderSystem.getModelViewStack().last().normal().set(poseStack.last().normal()); RenderSystem.applyModelViewMatrix(); if(!fbo.useDepth) @@ -243,6 +263,7 @@ public abstract class Control { RenderSystem.colorMask(true, true, true, true); RenderSystem.restoreProjectionMatrix(); poseStack.pose().popPose(); + RenderSystem.getModelViewStack().popPose(); RenderSystem.applyModelViewMatrix(); fbo.unbindWrite(); mc.getMainRenderTarget().bindWrite(true); diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/ControlGroup.java b/src/main/java/net/montoyo/wd/client/gui/controls/ControlGroup.java index e8425f2..ce32abf 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/ControlGroup.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/ControlGroup.java @@ -15,6 +15,8 @@ import net.montoyo.wd.client.gui.loading.JsonOWrapper; import net.montoyo.wd.utilities.Bounds; import org.lwjgl.opengl.GL11; +import java.util.Arrays; + import static org.lwjgl.opengl.GL11.*; public class ControlGroup extends Container { @@ -102,17 +104,18 @@ public class ControlGroup extends Container { if(visible) { poseStack.pose().pushPose(); + float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4); RenderSystem.setShaderColor(0.5f, 0.5f, 0.5f, 1.f); // RenderSystem.disableTexture(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - double x1 = (double) x; - double y1 = (double) y; - double x2 = (double) (x + width); - double y2 = (double) (y + height); + double x1 = x; + double y1 = y; + double x2 = (x + width); + double y2 = (y + height); double bp = 4.0; - double lw = (double) labelW; + double lw = labelW; x1 += bp; y1 += bp; @@ -161,6 +164,8 @@ public class ControlGroup extends Container { vBuffer.vertex(x2 - 1.0, y1, 0.0).endVertex(); tessellator.end(); + RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]); + RenderSystem.disableBlend(); // RenderSystem.enableTexture(); poseStack.pose().popPose(); @@ -179,6 +184,13 @@ public class ControlGroup extends Container { height = bounds.getHeight() + paddingY * 2; } + @Override + public void unfocus() { + for (Control control : childs) { + control.unfocus(); + } + } + @Override public void load(JsonOWrapper json) { super.load(json); diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/List.java b/src/main/java/net/montoyo/wd/client/gui/controls/List.java index b707751..4d7a62f 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/List.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/List.java @@ -10,12 +10,16 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.MultiBufferSource; import net.montoyo.wd.client.gui.loading.JsonOWrapper; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL20; import java.util.ArrayList; -import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; -import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.*; public class List extends BasicControl { @@ -97,19 +101,21 @@ public class List extends BasicControl { if(fbo != null) fbo.destroyBuffers(); - fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), false, Minecraft.ON_OSX); + fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), true, Minecraft.ON_OSX); fbo.setFilterMode(GL_NEAREST); - fbo.bindWrite(false); + fbo.bindWrite(true); RenderSystem.clearColor(0.0f, 0.0f, 0.0f, 1.f); //Set alpha to 1 RenderSystem.clearDepth(GL_COLOR_BUFFER_BIT); fbo.unbindWrite(); + mc.getMainRenderTarget().bindWrite(true); update = true; } - private void renderToFBO() { - GuiGraphics poseStack = beginFramebuffer(fbo, width, height); - poseStack.pose().pushPose(); - fillRect(0, 0, width, height, COLOR_BLACK); + private void renderToFBO(MultiBufferSource.BufferSource source) { + GuiGraphics graphics = beginFramebuffer(fbo, width, height); + GL11.glColorMask(true, true, true, true); + RenderSystem.applyModelViewMatrix(); + graphics.fill(0, 0, width, height, COLOR_BLACK); RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f); int offset = 4 - getYOffset(); @@ -121,13 +127,13 @@ public class List extends BasicControl { break; int color = (i == selected) ? selColor : COLOR_WHITE; - poseStack.drawString(font, content.get(i).text, 4, i * 12 + offset, color); + graphics.drawString(font, content.get(i).text, 4, i * 12 + offset, color); } } - drawBorder(poseStack, 0, 0, width, height, 0xFF808080); - endFramebuffer(poseStack, fbo); - poseStack.pose().popPose(); + graphics.renderOutline(0, 0, width, height, 0xFF808080); + graphics.flush(); + endFramebuffer(graphics, fbo); } @Override @@ -312,19 +318,18 @@ public class List extends BasicControl { } @Override - public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) { + public void draw(GuiGraphics graphics, int mouseX, int mouseY, float ptt) { if(visible) { if(update) { - renderToFBO(); + renderToFBO(graphics.bufferSource()); update = false; } - fbo.bindRead(); //TODO: Make sure is right + RenderSystem.setShaderTexture(0, fbo.getColorTextureId()); RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f); - fillTexturedRect(poseStack.pose(), x, y, width, height, 0.0, 1.0, 1.0, 0.0); - fbo.unbindRead(); + fillTexturedRect(graphics.pose(), x, y, width, height, 0.0, 1.0, 1.0, 0.0); - fillRect(x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040); + fillRect(graphics.bufferSource(), x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040); } } diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/TextField.java b/src/main/java/net/montoyo/wd/client/gui/controls/TextField.java index dc7d79a..7b90155 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/TextField.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/TextField.java @@ -99,15 +99,18 @@ public class TextField extends Control { public TextField() { field = new EditBox(font, 1, 1, 198, 20, Component.nullToEmpty("")); + setFocused(false); } public TextField(int x, int y, int width, int height) { field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty("")); + setFocused(false); } public TextField(int x, int y, int width, int height, String text) { field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty("")); field.setValue(text); + setFocused(false); } // TODO: make this public static in CefBrowserOSR @@ -166,11 +169,18 @@ public class TextField extends Control { @Override public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { - if (field.mouseClicked(mouseX, mouseY, mouseButton)) + if (field.mouseClicked(mouseX, mouseY, mouseButton)) { setFocused(true); + return true; + } return false; } - + + @Override + public void unfocus() { + setFocused(false); + } + @Override public boolean mouseReleased(double mouseX, double mouseY, int state) { return field.mouseReleased(mouseX, mouseY, state); @@ -262,7 +272,8 @@ public class TextField extends Control { public void setDisabled(boolean en) { enabled = !en; - field.setFocused(enabled); + if (!en) + field.setFocused(false); } public boolean isDisabled() { @@ -270,7 +281,6 @@ public class TextField extends Control { } public void enable() { - field.setFocused(true); enabled = true; } @@ -357,7 +367,7 @@ public class TextField extends Control { field.setTextColor(textColor); field.setTextColorUneditable(disabledColor); -// field.setFocus(enabled); + setFocused(false); } } diff --git a/src/main/java/net/montoyo/wd/client/gui/controls/UpgradeGroup.java b/src/main/java/net/montoyo/wd/client/gui/controls/UpgradeGroup.java index 8f54a08..6780e13 100644 --- a/src/main/java/net/montoyo/wd/client/gui/controls/UpgradeGroup.java +++ b/src/main/java/net/montoyo/wd/client/gui/controls/UpgradeGroup.java @@ -7,6 +7,7 @@ package net.montoyo.wd.client.gui.controls; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.world.item.ItemStack; import net.montoyo.wd.client.gui.loading.JsonOWrapper; @@ -33,10 +34,10 @@ public class UpgradeGroup extends BasicControl { for(ItemStack is: upgrades) { if(is == overStack && !disabled) - fillRect(x, y, 16, 16, 0x80FF0000); + fillRect(poseStack.bufferSource(), x, y, 16, 16, 0x80FF0000); -// renderItem.renderAndDecorateItem(mc.player, is, x, y, 0); -// renderItem.renderAndDecorateItem(is, font.lineHeight, x, y); //TODO is lineHeight right? + poseStack.renderItem(is, x, y); + poseStack.renderItemDecorations(font, is, x, y); x += 18; } } diff --git a/src/main/java/net/montoyo/wd/controls/ScreenControlRegistry.java b/src/main/java/net/montoyo/wd/controls/ScreenControlRegistry.java index 477baf3..3d85d8e 100644 --- a/src/main/java/net/montoyo/wd/controls/ScreenControlRegistry.java +++ b/src/main/java/net/montoyo/wd/controls/ScreenControlRegistry.java @@ -63,6 +63,7 @@ public class ScreenControlRegistry { register(ManageRightsAndUpdgradesControl.id, new ScreenControlType<>(ManageRightsAndUpdgradesControl.class, ManageRightsAndUpdgradesControl::new)); register(ClickControl.id, new ScreenControlType<>(ClickControl.class, ClickControl::new)); register(OwnerControl.id, new ScreenControlType<>(OwnerControl.class, OwnerControl::new)); + register(TurnOffControl.id, new ScreenControlType<>(TurnOffControl.class, (buf) -> TurnOffControl.INSTANCE)); } public static ScreenControl parse(FriendlyByteBuf buf) { diff --git a/src/main/java/net/montoyo/wd/controls/builtin/TurnOffControl.java b/src/main/java/net/montoyo/wd/controls/builtin/TurnOffControl.java new file mode 100644 index 0000000..13a5d13 --- /dev/null +++ b/src/main/java/net/montoyo/wd/controls/builtin/TurnOffControl.java @@ -0,0 +1,49 @@ +package net.montoyo.wd.controls.builtin; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent; +import net.montoyo.wd.WebDisplays; +import net.montoyo.wd.controls.ScreenControl; +import net.montoyo.wd.core.MissingPermissionException; +import net.montoyo.wd.entity.TileEntityScreen; +import net.montoyo.wd.utilities.BlockSide; +import net.montoyo.wd.utilities.NameUUIDPair; + +import java.util.function.Function; + +public class TurnOffControl extends ScreenControl { + public static final ResourceLocation id = new ResourceLocation("webdisplays:deactivate"); + + public static final TurnOffControl INSTANCE = new TurnOffControl(); + + public TurnOffControl() { + super(id); + } + + @Override + public void write(FriendlyByteBuf buf) { + } + + @Override + public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function permissionChecker) throws MissingPermissionException { + throw new RuntimeException("Cannot handle deactivation packet from server"); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) { + if (side != null) { + WebDisplays.PROXY.closeGui(pos, side); + tes.disableScreen(side); + } else { + for (BlockSide value : BlockSide.values()) { + WebDisplays.PROXY.closeGui(pos, value); + tes.disableScreen(value); + } + } + } +} diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java index 368a467..d155b33 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java @@ -6,6 +6,7 @@ package net.montoyo.wd.entity; import com.cinemamod.mcef.MCEF; import com.cinemamod.mcef.MCEFBrowser; +import com.cinemamod.mcef.MCEFCursorChangeListener; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -63,7 +64,7 @@ public class TileEntityScreen extends BlockEntity { public TileEntityScreen(BlockPos arg2, BlockState arg3) { super(TileInit.SCREEN_BLOCK_ENTITY.get(), arg2, arg3); } - + public static class Screen { public BlockSide side; @@ -233,7 +234,7 @@ public class TileEntityScreen extends BlockEntity { else mcefBrowser.resize(resolution.x, resolution.y); - mcefBrowser.setCursorChangeListener((type) -> mouseType = type); + mcefBrowser.setCursorChangeListener((MCEFCursorChangeListener) (type) -> mouseType = type); } doTurnOnAnim = doAnim; @@ -1139,7 +1140,27 @@ public class TileEntityScreen extends BlockEntity { scr.upgrades.clear(); } - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageCloseGui(getBlockPos())); + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.turnOff(getBlockPos(), null)); + } + + public void disableScreen(BlockSide side) { + Screen remove = null; + for (Screen screen : screens) { + if (screen.side == side) { + remove = screen; + break; + } + } + + if (remove == null) return; + + if (level != null && !level.isClientSide) { + final Screen scrn = remove; + remove.upgrades.forEach(is -> dropUpgrade(is, scrn.side, null)); + } + + remove.upgrades.clear(); + screens.remove(remove); } public void setOwner(BlockSide side, Player newOwner) { diff --git a/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java b/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java index 94cc668..05c7bf5 100644 --- a/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java +++ b/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java @@ -86,7 +86,13 @@ public class S2CMessageScreenUpdate extends Packet { screenUpdate.control = new OwnerControl(owner); return screenUpdate; } - + + public static S2CMessageScreenUpdate turnOff(BlockPos blockPos, BlockSide side) { + S2CMessageScreenUpdate screenUpdate = new S2CMessageScreenUpdate(blockPos, side); + screenUpdate.control = TurnOffControl.INSTANCE; + return screenUpdate; + } + @Override public void write(FriendlyByteBuf buf) { buf.writeBlockPos(pos);