diff --git a/libs/mcef-2.x.jar b/libs/mcef-2.x.jar index ba5160d..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 06fab8f..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; @@ -262,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/controls/ControlGroup.java b/src/main/java/net/montoyo/wd/client/gui/controls/ControlGroup.java index ea162f3..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 @@ -110,12 +110,12 @@ public class ControlGroup extends Container { 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; 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 24ce5d4..d155b33 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java @@ -64,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; @@ -1140,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);