diff --git a/src/main/java/net/montoyo/wd/client/ClientProxy.java b/src/main/java/net/montoyo/wd/client/ClientProxy.java index 0f7b25a..561fd79 100644 --- a/src/main/java/net/montoyo/wd/client/ClientProxy.java +++ b/src/main/java/net/montoyo/wd/client/ClientProxy.java @@ -132,12 +132,12 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { BlockEntityRenderers.register(TileInit.SCREEN_BLOCK_ENTITY.get(), new ScreenRenderer.ScreenRendererProvider()); + registerBlockRenderLayers(RenderType.cutout(), BlockInit.blockKeyBoard.get(), BlockInit.blockKbRight.get()); } @SubscribeEvent public static void onModelRegistryEvent(ModelEvent.RegisterGeometryLoaders event) { event.register(ScreenModelLoader.SCREEN_LOADER.getPath(), new ScreenModelLoader()); - registerBlockRenderLayers(RenderType.cutout(), BlockInit.blockKeyBoard.get(), BlockInit.blockKbRight.get()); } private static void registerBlockRenderLayers(RenderType layer, Block... blocks) { diff --git a/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java b/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java index 593940c..144c034 100644 --- a/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java +++ b/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java @@ -25,6 +25,7 @@ import net.montoyo.wd.utilities.BlockSide; import net.montoyo.wd.utilities.Util; import net.montoyo.wd.utilities.Vector3i; +import java.io.IOException; import java.util.Map; @Mod.EventBusSubscriber(Dist.CLIENT) @@ -101,6 +102,13 @@ public class GuiSetURL2 extends WDScreen { private void validate(String url) { if(!url.isEmpty()) { + + try { + TileEntityScreen.url(url); + } catch (IOException e) { + throw new RuntimeException(e); + } + url = Util.addProtocol(url); url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url); diff --git a/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java b/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java index ae0e803..e1146c0 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java +++ b/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java @@ -20,6 +20,8 @@ import net.montoyo.wd.utilities.Vector3f; import net.montoyo.wd.utilities.Vector3i; import org.jetbrains.annotations.NotNull; +import java.io.IOException; + import static com.mojang.math.Vector3f.*; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityInterfaceBase.java b/src/main/java/net/montoyo/wd/entity/TileEntityInterfaceBase.java index ac857af..247dbad 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityInterfaceBase.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityInterfaceBase.java @@ -17,6 +17,7 @@ import net.montoyo.wd.net.client.CMessageScreenUpdate; import net.montoyo.wd.utilities.*; import javax.annotation.Nonnull; +import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -336,7 +337,11 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase { else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.CHANGE_URL) == 0) return err("restrictions"); else { - scr.setScreenURL(screenSide, url); + try { + scr.setScreenURL(screenSide, url); + } catch (IOException e) { + throw new RuntimeException(e); + } return TRUE; } } diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityRedCtrl.java b/src/main/java/net/montoyo/wd/entity/TileEntityRedCtrl.java index 2ca0328..397aa46 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityRedCtrl.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityRedCtrl.java @@ -22,6 +22,7 @@ import net.montoyo.wd.utilities.BlockSide; import net.montoyo.wd.utilities.Util; import javax.annotation.Nonnull; +import java.io.IOException; public class TileEntityRedCtrl extends TileEntityPeripheralBase { @@ -115,8 +116,12 @@ public class TileEntityRedCtrl extends TileEntityPeripheralBase { if(isScreenChunkLoaded()) { TileEntityScreen tes = getConnectedScreen(); - if(tes != null) - tes.setScreenURL(screenSide, url); + if (tes != null) + try { + tes.setScreenURL(screenSide, url); + } catch (IOException e) { + throw new RuntimeException(e); + } } } } diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java index a05ff35..0f26dc0 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java @@ -8,6 +8,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; @@ -42,6 +43,8 @@ import net.montoyo.wd.utilities.*; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.IOException; +import java.net.*; import java.util.ArrayList; import java.util.Collections; import java.util.UUID; @@ -49,7 +52,7 @@ import java.util.function.Consumer; import static net.montoyo.wd.block.BlockPeripheral.point; -public class TileEntityScreen extends BlockEntity{ +public class TileEntityScreen extends BlockEntity { public TileEntityScreen(BlockPos arg2, BlockState arg3) { super(TileInit.SCREEN_BLOCK_ENTITY.get(), arg2, arg3); @@ -85,7 +88,7 @@ public class TileEntityScreen extends BlockEntity{ ret.url = tag.getString("URL"); ret.videoType = VideoType.getTypeFromURL(ret.url); - if(ret.resolution.x <= 0 || ret.resolution.y <= 0) { + if (ret.resolution.x <= 0 || ret.resolution.y <= 0) { float psx = ((float) ret.size.x) * 16.f - 4.f; float psy = ((float) ret.size.y) * 16.f - 4.f; psx *= 8.f; //TODO: Use ratio in config file @@ -95,7 +98,7 @@ public class TileEntityScreen extends BlockEntity{ ret.resolution.y = (int) psy; } - if(tag.contains("OwnerName")) { + if (tag.contains("OwnerName")) { String name = tag.getString("OwnerName"); UUID uuid = tag.getUUID("OwnerUUID"); ret.owner = new NameUUIDPair(name, uuid); @@ -104,7 +107,7 @@ public class TileEntityScreen extends BlockEntity{ ListTag friends = tag.getList("Friends", 10); ret.friends = new ArrayList<>(friends.size()); - for(int i = 0; i < friends.size(); i++) { + for (int i = 0; i < friends.size(); i++) { CompoundTag nf = friends.getCompound(i); NameUUIDPair pair = new NameUUIDPair(nf.getString("Name"), nf.getUUID("UUID")); ret.friends.add(pair); @@ -116,10 +119,10 @@ public class TileEntityScreen extends BlockEntity{ ListTag upgrades = tag.getList("Upgrades", 10); ret.upgrades = new ArrayList<>(); - for(int i = 0; i < upgrades.size(); i++) + for (int i = 0; i < upgrades.size(); i++) ret.upgrades.add(new ItemStack((ItemLike) upgrades.getCompound(i))); - if(tag.contains("AutoVolume")) + if (tag.contains("AutoVolume")) ret.autoVolume = tag.getBoolean("AutoVolume"); return ret; @@ -135,7 +138,7 @@ public class TileEntityScreen extends BlockEntity{ tag.putByte("Rotation", (byte) rotation.ordinal()); tag.putString("URL", url); - if(owner == null) + if (owner == null) Log.warning("Found TES with NO OWNER!!"); else { tag.putString("OwnerName", owner.name); @@ -143,7 +146,7 @@ public class TileEntityScreen extends BlockEntity{ } ListTag list = new ListTag(); - for(NameUUIDPair f: friends) { + for (NameUUIDPair f : friends) { CompoundTag nf = new CompoundTag(); nf.putString("Name", f.name); nf.putUUID("UUID", f.uuid); @@ -156,7 +159,7 @@ public class TileEntityScreen extends BlockEntity{ tag.putByte("OtherRights", (byte) otherRights); list = new ListTag(); - for(ItemStack is: upgrades) + for (ItemStack is : upgrades) list.add(is.save(new CompoundTag())); tag.put("Upgrades", list); @@ -169,19 +172,19 @@ public class TileEntityScreen extends BlockEntity{ } public int rightsFor(UUID uuid) { - if(owner.uuid.equals(uuid)) + if (owner.uuid.equals(uuid)) return ScreenRights.ALL; return friends.stream().anyMatch(f -> f.uuid.equals(uuid)) ? friendRights : otherRights; } public void setupRedstoneStatus(Level world, BlockPos start) { - if(world.isClientSide()) { + if (world.isClientSide()) { Log.warning("Called Screen.setupRedstoneStatus() on client."); return; } - if(redstoneStatus != null) { + if (redstoneStatus != null) { Log.warning("Called Screen.setupRedstoneStatus() on server, but redstone status is non-null"); return; } @@ -191,25 +194,24 @@ public class TileEntityScreen extends BlockEntity{ final Direction facing = VALUES[side.reverse().ordinal()]; final ScreenIterator it = new ScreenIterator(start, side, size); - while(it.hasNext()) { + while (it.hasNext()) { int idx = it.getIndex(); redstoneStatus.set(idx, world.getSignal(it.next(), facing)); } } - public void clampResolution() { - if(resolution.x > WebDisplays.INSTANCE.maxResX) { - float newY = ((float) resolution.y) * ((float) WebDisplays.INSTANCE.maxResX) / ((float) resolution.x); - resolution.x = WebDisplays.INSTANCE.maxResX; + if (resolution.x > WebDisplays.INSTANCE.maxResX) { + float newY = ((float) resolution.y) * ((float) WebDisplays.INSTANCE.maxResX) / ((float) resolution.x); + resolution.x = WebDisplays.INSTANCE.maxResX; resolution.y = (int) newY; } - if(resolution.y > WebDisplays.INSTANCE.maxResY) { - float newX = ((float) resolution.x) * ((float) WebDisplays.INSTANCE.maxResY) / ((float) resolution.y); + if (resolution.y > WebDisplays.INSTANCE.maxResY) { + float newX = ((float) resolution.x) * ((float) WebDisplays.INSTANCE.maxResY) / ((float) resolution.y); resolution.x = (int) newX; - resolution.y = WebDisplays.INSTANCE.maxResY; + resolution.y = WebDisplays.INSTANCE.maxResY; } } @@ -218,10 +220,10 @@ public class TileEntityScreen extends BlockEntity{ public void forEachScreenBlocks(BlockSide side, Consumer func) { Screen scr = getScreen(side); - if(scr != null) { + if (scr != null) { ScreenIterator it = new ScreenIterator(getBlockPos(), side, scr.size); - while(it.hasNext()) + while (it.hasNext()) func.accept(it.next()); } } @@ -240,8 +242,8 @@ public class TileEntityScreen extends BlockEntity{ } public void unload() { - for(Screen scr: screens) { - if(scr.browser != null) { + for (Screen scr : screens) { + if (scr.browser != null) { scr.browser.close(); scr.browser = null; } @@ -255,11 +257,11 @@ public class TileEntityScreen extends BlockEntity{ super.deserializeNBT(tag); ListTag list = tag.getList("WDScreens", 10); - if(list.isEmpty()) + if (list.isEmpty()) return; screens.clear(); - for(int i = 0; i < list.size(); i++) + for (int i = 0; i < list.size(); i++) screens.add(Screen.deserialize(list.getCompound(i))); } @@ -270,7 +272,7 @@ public class TileEntityScreen extends BlockEntity{ super.serializeNBT(); ListTag list = new ListTag(); - for(Screen scr: screens) + for (Screen scr : screens) list.add(scr.serialize()); tag.put("WDScreens", list); @@ -278,30 +280,30 @@ public class TileEntityScreen extends BlockEntity{ } public Screen addScreen(BlockSide side, Vector2i size, @Nullable Vector2i resolution, @Nullable Player owner, boolean sendUpdate) { - for(Screen scr: screens) { - if(scr.side == side) + for (Screen scr : screens) { + if (scr.side == side) return scr; } Screen ret = new Screen(); ret.side = side; ret.size = size; - ret.url = WebDisplays.INSTANCE.homePage; + ret.url = WebDisplays.INSTANCE.homePage; ret.friends = new ArrayList<>(); ret.friendRights = ScreenRights.DEFAULTS; ret.otherRights = ScreenRights.DEFAULTS; ret.upgrades = new ArrayList<>(); - if(owner != null) { + if (owner != null) { ret.owner = new NameUUIDPair(owner.getGameProfile()); - if(side == BlockSide.TOP || side == BlockSide.BOTTOM) { + if (side == BlockSide.TOP || side == BlockSide.BOTTOM) { int rot = (int) Math.floor(((double) (owner.getYRot() * 4.0f / 360.0f)) + 2.5) & 3; - if(side == BlockSide.TOP) { - if(rot == 1) + if (side == BlockSide.TOP) { + if (rot == 1) rot = 3; - else if(rot == 3) + else if (rot == 3) rot = 1; } @@ -309,7 +311,7 @@ public class TileEntityScreen extends BlockEntity{ } } - if(resolution == null || resolution.x < 1 || resolution.y < 1) { + if (resolution == null || resolution.x < 1 || resolution.y < 1) { float psx = ((float) size.x) * 16.f - 4.f; float psy = ((float) size.y) * 16.f - 4.f; psx *= 8.f; //TODO: Use ratio in config file @@ -321,16 +323,16 @@ public class TileEntityScreen extends BlockEntity{ ret.clampResolution(); - if(!level.isClientSide) { + if (!level.isClientSide) { ret.setupRedstoneStatus(level, getBlockPos()); - if(sendUpdate) + if (sendUpdate) Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new CMessageAddScreen(this, ret)); } screens.add(ret); - if(level.isClientSide) + if (level.isClientSide) updateAABB(); else setChanged(); @@ -339,8 +341,8 @@ public class TileEntityScreen extends BlockEntity{ } public Screen getScreen(BlockSide side) { - for(Screen scr: screens) { - if(scr.side == side) + for (Screen scr : screens) { + if (scr.side == side) return scr; } @@ -358,51 +360,70 @@ public class TileEntityScreen extends BlockEntity{ public void clear() { screens.clear(); - if(!level.isClientSide) + if (!level.isClientSide) setChanged(); } public void requestData(ServerPlayer ep) { - if(!level.isClientSide) + if (!level.isClientSide) Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> ep), new CMessageAddScreen(this)); } - public void setScreenURL(BlockSide side, String url) { + public static String url(String url) throws IOException { + + MinecraftServer server = WebDisplays.PROXY.getServer(); + System.setProperty("http.proxyHost", server.getLocalIp()); + System.setProperty("http.proxyPort", String.valueOf(server.getPort())); + Proxy webProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByName(server.getLocalIp()), server.getPort())); + + URL weburl1 = new URL(url); + + HttpURLConnection webProxyConnection = (HttpURLConnection) weburl1.openConnection(webProxy); + + return webProxyConnection.getURL().toString(); + } + + public void setScreenURL(BlockSide side, String url) throws IOException { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Attempt to change URL of non-existing screen on side %s", side.toString()); return; } - url = WebDisplays.applyBlacklist(url); - scr.url = url; - scr.videoType = VideoType.getTypeFromURL(url); + String weburl = url(url); - if(level.isClientSide) { - if(scr.browser != null) - scr.browser.loadURL(url); + weburl = WebDisplays.applyBlacklist(weburl); + scr.url = weburl; + scr.videoType = VideoType.getTypeFromURL(weburl); + + if (level.isClientSide) { + if (scr.browser != null) + scr.browser.loadURL(weburl); } else { - Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.setURL(this, side, url)); + Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.setURL(this, side, weburl)); setChanged(); } + + System.setProperty("http.proxyHost", null); + System.setProperty("http.proxyPort", null); } public void removeScreen(BlockSide side) { int idx = -1; - for(int i = 0; i < screens.size(); i++) { - if(screens.get(i).side == side) { + for (int i = 0; i < screens.size(); i++) { + if (screens.get(i).side == side) { idx = i; break; } } - if(idx < 0) { + if (idx < 0) { Log.error("Tried to delete non-existing screen on side %s", side.toString()); return; } - if(level.isClientSide) { - if(screens.get(idx).browser != null) { + if (level.isClientSide) { + if (screens.get(idx).browser != null) { screens.get(idx).browser.close(); screens.get(idx).browser = null; } @@ -411,8 +432,8 @@ public class TileEntityScreen extends BlockEntity{ screens.remove(idx); - if(!level.isClientSide) { - if(screens.isEmpty()) //No more screens: remove tile entity + if (!level.isClientSide) { + if (screens.isEmpty()) //No more screens: remove tile entity level.setBlockAndUpdate(getBlockPos(), BlockInit.blockScreen.get().defaultBlockState().setValue(BlockScreen.hasTE, false)); else setChanged(); @@ -420,13 +441,13 @@ public class TileEntityScreen extends BlockEntity{ } public void setResolution(BlockSide side, Vector2i res) { - if(res.x < 1 || res.y < 1) { + if (res.x < 1 || res.y < 1) { Log.warning("Call to TileEntityScreen.setResolution(%s) with suspicious values X=%d and Y=%d", side.toString(), res.x, res.y); return; } Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to change resolution of non-existing screen on side %s", side.toString()); return; } @@ -434,10 +455,10 @@ public class TileEntityScreen extends BlockEntity{ scr.resolution = res; scr.clampResolution(); - if(level.isClientSide) { + if (level.isClientSide) { WebDisplays.PROXY.screenUpdateResolutionInGui(new Vector3i(getBlockPos()), side, res); - if(scr.browser != null) { + if (scr.browser != null) { scr.browser.close(); scr.browser = null; //Will be re-created by renderer } @@ -448,8 +469,8 @@ public class TileEntityScreen extends BlockEntity{ } private static Player getLaserUser(Screen scr) { - if(scr.laserUser != null) { - if(scr.laserUser.isRemoved() || !scr.laserUser.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemInit.itemLaserPointer.get())) + if (scr.laserUser != null) { + if (scr.laserUser.isRemoved() || !scr.laserUser.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemInit.itemLaserPointer.get())) scr.laserUser = null; } @@ -457,32 +478,32 @@ public class TileEntityScreen extends BlockEntity{ } private static void checkLaserUserRights(Screen scr) { - if(scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.CLICK) == 0) + if (scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.CLICK) == 0) scr.laserUser = null; } public void clearLaserUser(BlockSide side) { Screen scr = getScreen(side); - if(scr != null) + if (scr != null) scr.laserUser = null; } public void click(BlockSide side, Vector2i vec) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Attempt click non-existing screen of side %s", side.toString()); return; } - if(level.isClientSide) + if (level.isClientSide) Log.warning("TileEntityScreen.click() from client side is useless..."); - else if(getLaserUser(scr) == null) + else if (getLaserUser(scr) == null) Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.click(this, side, CMessageScreenUpdate.MOUSE_CLICK, vec)); } void clickUnsafe(BlockSide side, int action, int x, int y) { - if(level.isClientSide) { + if (level.isClientSide) { Vector2i vec = (action == CMessageScreenUpdate.MOUSE_UP) ? null : new Vector2i(x, y); Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.click(this, side, action, vec)); } @@ -490,25 +511,25 @@ public class TileEntityScreen extends BlockEntity{ public void handleMouseEvent(BlockSide side, int event, @Nullable Vector2i vec) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Attempt inject mouse events on non-existing screen of side %s", side.toString()); return; } - if(scr.browser != null) { - if(event == CMessageScreenUpdate.MOUSE_CLICK) { + if (scr.browser != null) { + if (event == CMessageScreenUpdate.MOUSE_CLICK) { scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move to target scr.browser.injectMouseButton(vec.x, vec.y, 0, 1, true, 1); //Press scr.browser.injectMouseButton(vec.x, vec.y, 0, 1, false, 1); //Release - } else if(event == CMessageScreenUpdate.MOUSE_DOWN) { + } else if (event == CMessageScreenUpdate.MOUSE_DOWN) { scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move to target scr.browser.injectMouseButton(vec.x, vec.y, 0, 1, true, 1); //Press - } else if(event == CMessageScreenUpdate.MOUSE_MOVE) + } else if (event == CMessageScreenUpdate.MOUSE_MOVE) scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move - else if(event == CMessageScreenUpdate.MOUSE_UP) + else if (event == CMessageScreenUpdate.MOUSE_UP) scr.browser.injectMouseButton(scr.lastMousePos.x, scr.lastMousePos.y, 0, 1, false, 1); //Release - if(vec != null) { + if (vec != null) { scr.lastMousePos.x = vec.x; scr.lastMousePos.y = vec.y; } @@ -517,71 +538,71 @@ public class TileEntityScreen extends BlockEntity{ public void updateJSRedstone(BlockSide side, Vector2i vec, int redstoneLevel) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Called updateJSRedstone on non-existing side %s", side.toString()); return; } - if(level.isClientSide) { - if(scr.browser != null) + if (level.isClientSide) { + if (scr.browser != null) scr.browser.runJS("if(typeof webdisplaysRedstoneCallback == \"function\") webdisplaysRedstoneCallback(" + vec.x + ", " + vec.y + ", " + redstoneLevel + ");", ""); } else { boolean sendMsg = false; - if(scr.redstoneStatus == null) { + if (scr.redstoneStatus == null) { scr.setupRedstoneStatus(level, getBlockPos()); sendMsg = true; } else { int idx = vec.y * scr.size.x + vec.x; - if(scr.redstoneStatus.get(idx) != redstoneLevel) { + if (scr.redstoneStatus.get(idx) != redstoneLevel) { scr.redstoneStatus.set(idx, redstoneLevel); sendMsg = true; } } - if(sendMsg) - Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel)); + if (sendMsg) + Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel)); } } public void handleJSRequest(ServerPlayer src, BlockSide side, int reqId, JSServerRequest req, Object[] data) { - if(level.isClientSide) { + if (level.isClientSide) { Log.error("Called handleJSRequest client-side"); return; } Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Called handleJSRequest on non-existing side %s", side.toString()); Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, 403, "Invalid side")); return; } - if(!scr.owner.uuid.equals(src.getGameProfile().getId())) { + if (!scr.owner.uuid.equals(src.getGameProfile().getId())) { Log.warning("Player %s (UUID %s) tries to use the redstone output API on a screen he doesn't own!", src.getName(), src.getGameProfile().getId().toString()); Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, 403, "Only the owner can do that")); return; } - if(scr.upgrades.stream().noneMatch(DefaultUpgrade.REDOUTPUT::matches)) { + if (scr.upgrades.stream().noneMatch(DefaultUpgrade.REDOUTPUT::matches)) { Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, 403, "Missing upgrade")); return; } - if(req == JSServerRequest.CLEAR_REDSTONE) { + if (req == JSServerRequest.CLEAR_REDSTONE) { final BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos(); final Vector3i vec1 = new Vector3i(getBlockPos()); final Vector3i vec2 = new Vector3i(); - for(int y = 0; y < scr.size.y; y++) { + for (int y = 0; y < scr.size.y; y++) { vec2.set(vec1); - for(int x = 0; x < scr.size.x; x++) { + for (int x = 0; x < scr.size.x; x++) { vec2.toBlock(mbp); BlockState bs = level.getBlockState(mbp); - if(bs.getValue(BlockScreen.emitting)) + if (bs.getValue(BlockScreen.emitting)) level.setBlock(mbp, bs.setValue(BlockScreen.emitting, false), Block.UPDATE_ALL_IMMEDIATE); vec2.add(side.right.x, side.right.y, side.right.z); @@ -591,18 +612,18 @@ public class TileEntityScreen extends BlockEntity{ } Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, new byte[0])); - } else if(req == JSServerRequest.SET_REDSTONE_AT) { + } else if (req == JSServerRequest.SET_REDSTONE_AT) { int x = (Integer) data[0]; int y = (Integer) data[1]; boolean state = (Boolean) data[2]; - if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) + if (x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, 403, "Out of range")); else { BlockPos bp = (new Vector3i(getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock(); BlockState bs = level.getBlockState(bp); - if(!bs.getValue(BlockScreen.emitting).equals(state)) + if (!bs.getValue(BlockScreen.emitting).equals(state)) level.setBlockAndUpdate(bp, bs.setValue(BlockScreen.emitting, state)); Messages.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new CMessageJSResponse(reqId, req, new byte[0])); @@ -613,7 +634,7 @@ public class TileEntityScreen extends BlockEntity{ @Override public void onLoad() { - if(level.isClientSide) { + if (level.isClientSide) { Messages.INSTANCE.sendToServer(new SMessageRequestTEData(this)); WebDisplays.PROXY.trackScreen(this, true); } @@ -621,11 +642,11 @@ public class TileEntityScreen extends BlockEntity{ @Override public void onChunkUnloaded() { - if(level.isClientSide) { + if (level.isClientSide) { WebDisplays.PROXY.trackScreen(this, false); - for(Screen scr: screens) { - if(scr.browser != null) { + for (Screen scr : screens) { + if (scr.browser != null) { scr.browser.close(); scr.browser = null; } @@ -638,7 +659,7 @@ public class TileEntityScreen extends BlockEntity{ Vector3i tmp = new Vector3i(); AABB aabb = new AABB(origin); - for(Screen scr: screens) { + for (Screen scr : screens) { tmp.set(origin); tmp.addMul(scr.side.right, scr.size.x); tmp.addMul(scr.side.up, scr.size.y); @@ -663,20 +684,20 @@ public class TileEntityScreen extends BlockEntity{ int intPart = 0; //Need to initialize those because the compiler is stupid int fracPart = 0; - for(Screen scr: screens) { - if(scr.autoVolume && scr.videoType != null && scr.browser != null && !scr.browser.isPageLoading()) { - if(needsComputation) { + for (Screen scr : screens) { + if (scr.autoVolume && scr.videoType != null && scr.browser != null && !scr.browser.isPageLoading()) { + if (needsComputation) { float dist = (float) Math.sqrt(d); float vol; - if(dist <= wd.avDist100) + if (dist <= wd.avDist100) vol = masterVolume * wd.ytVolume; - else if(dist >= wd.avDist0) + else if (dist >= wd.avDist0) vol = 0.0f; else vol = (1.0f - (dist - wd.avDist100) / (wd.avDist0 - wd.avDist100)) * masterVolume * wd.ytVolume; - if(Math.abs(ytVolume - vol) < 0.5f) + if (Math.abs(ytVolume - vol) < 0.5f) return; //Delta is too small ytVolume = vol; @@ -691,14 +712,14 @@ public class TileEntityScreen extends BlockEntity{ } public void updateClientSideURL(IBrowser target, String url) { - for(Screen scr: screens) { - if(scr.browser == target) { + for (Screen scr : screens) { + if (scr.browser == target) { boolean blacklisted = WebDisplays.isSiteBlacklisted(url); scr.url = blacklisted ? WebDisplays.BLACKLIST_URL : url; //FIXME: This is an invalid fix for something that CANNOT be fixed scr.videoType = VideoType.getTypeFromURL(scr.url); ytVolume = Float.POSITIVE_INFINITY; //Force volume update - if(blacklisted && scr.browser != null) + if (blacklisted && scr.browser != null) scr.browser.loadURL(WebDisplays.BLACKLIST_URL); break; @@ -710,19 +731,19 @@ public class TileEntityScreen extends BlockEntity{ public void invalidateCaps() { super.invalidateCaps(); - if(level.isClientSide) + if (level.isClientSide) onChunkUnloaded(); } public void addFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { - if(!level.isClientSide) { + if (!level.isClientSide) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to add friend to invalid screen side %s", side.toString()); return; } - if(!scr.friends.contains(pair)) { + if (!scr.friends.contains(pair)) { scr.friends.add(pair); (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); setChanged(); @@ -731,14 +752,14 @@ public class TileEntityScreen extends BlockEntity{ } public void removeFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { - if(!level.isClientSide) { + if (!level.isClientSide) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to remove friend from invalid screen side %s", side.toString()); return; } - if(scr.friends.remove(pair)) { + if (scr.friends.remove(pair)) { checkLaserUserRights(scr); (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); setChanged(); @@ -747,9 +768,9 @@ public class TileEntityScreen extends BlockEntity{ } public void setRights(ServerPlayer ply, BlockSide side, int fr, int or) { - if(!level.isClientSide) { + if (!level.isClientSide) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to change rights of invalid screen on side %s", side.toString()); return; } @@ -765,18 +786,18 @@ public class TileEntityScreen extends BlockEntity{ public void type(BlockSide side, String text, BlockPos soundPos) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to type on invalid screen on side %s", side.toString()); return; } - if(level.isClientSide) { - if(scr.browser != null) { + if (level.isClientSide) { + if (scr.browser != null) { try { - if(text.startsWith("t")) { - for(int i = 1; i < text.length(); i++) { + if (text.startsWith("t")) { + for (int i = 1; i < text.length(); i++) { char chr = text.charAt(i); - if(chr == 1) + if (chr == 1) break; scr.browser.injectKeyTyped(chr, 0); @@ -784,24 +805,26 @@ public class TileEntityScreen extends BlockEntity{ } else { TypeData[] data = WebDisplays.GSON.fromJson(text, TypeData[].class); - for(TypeData ev : data) { + for (TypeData ev : data) { switch (ev.getAction()) { - case PRESS -> scr.browser.injectKeyPressedByKeyCode(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); - case RELEASE -> scr.browser.injectKeyReleasedByKeyCode(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); + case PRESS -> + scr.browser.injectKeyPressedByKeyCode(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); + case RELEASE -> + scr.browser.injectKeyReleasedByKeyCode(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); case TYPE -> scr.browser.injectKeyTyped(ev.getKeyCode(), ev.getModifier()); default -> throw new RuntimeException("Invalid type action '" + ev.getAction() + '\''); } } } - } catch(Throwable t) { + } catch (Throwable t) { Log.warningEx("Suspicious keyboard type packet received...", t); } } } else { Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.type(this, side, text)); - if(soundPos != null) - playSoundAt( WebDisplays.INSTANCE.soundTyping, soundPos, 0.25f, 1.f); + if (soundPos != null) + playSoundAt(WebDisplays.INSTANCE.soundTyping, soundPos, 0.25f, 1.f); } } @@ -814,13 +837,13 @@ public class TileEntityScreen extends BlockEntity{ } public void updateUpgrades(BlockSide side, ItemStack[] upgrades) { - if(!level.isClientSide) { + if (!level.isClientSide) { Log.error("Tried to call TileEntityScreen.updateUpgrades() from server side..."); return; } Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to update upgrades on invalid screen on side %s", side.toString()); return; } @@ -828,7 +851,7 @@ public class TileEntityScreen extends BlockEntity{ scr.upgrades.clear(); Collections.addAll(scr.upgrades, upgrades); - if(scr.browser != null) + if (scr.browser != null) scr.browser.runJS("if(typeof webdisplaysUpgradesChanged == \"function\") webdisplaysUpgradesChanged();", ""); } @@ -838,27 +861,27 @@ public class TileEntityScreen extends BlockEntity{ //If equal is null, no duplicate check is preformed public boolean addUpgrade(BlockSide side, ItemStack is, @Nullable Player player, boolean abortIfExisting) { - if(level.isClientSide) + if (level.isClientSide) return false; Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to add an upgrade on invalid screen on side %s", side.toString()); return false; } - if(!(is.getItem() instanceof IUpgrade)) { + if (!(is.getItem() instanceof IUpgrade)) { Log.error("Tried to add a non-upgrade item %s to screen (%s does not implement IUpgrade)", safeName(is), is.getItem().getClass().getCanonicalName()); return false; } - if(scr.upgrades.size() >= 16) { + if (scr.upgrades.size() >= 16) { Log.error("Can't insert upgrade %s in screen %s at %s: too many upgrades already!", safeName(is), side.toString(), getBlockPos().toString()); return false; } IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); - if(abortIfExisting && scr.upgrades.stream().anyMatch(otherStack -> itemAsUpgrade.isSameUpgrade(is, otherStack))) + if (abortIfExisting && scr.upgrades.stream().anyMatch(otherStack -> itemAsUpgrade.isSameUpgrade(is, otherStack))) return false; //Upgrade already exists ItemStack isCopy = is.copy(); //FIXME: Duct tape fix, because the original stack will be shrinked @@ -874,10 +897,10 @@ public class TileEntityScreen extends BlockEntity{ public boolean hasUpgrade(BlockSide side, ItemStack is) { Screen scr = getScreen(side); - if(scr == null) + if (scr == null) return false; - if(!(is.getItem() instanceof IUpgrade)) + if (!(is.getItem() instanceof IUpgrade)) return false; IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); @@ -890,16 +913,16 @@ public class TileEntityScreen extends BlockEntity{ } public void removeUpgrade(BlockSide side, ItemStack is, @Nullable Player player) { - if(level.isClientSide) + if (level.isClientSide) return; Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Tried to remove an upgrade on invalid screen on side %s", side.toString()); return; } - if(!(is.getItem() instanceof IUpgrade)) { + if (!(is.getItem() instanceof IUpgrade)) { Log.error("Tried to remove a non-upgrade item %s to screen (%s does not implement IUpgrade)", safeName(is), is.getItem().getClass().getCanonicalName()); return; } @@ -907,14 +930,14 @@ public class TileEntityScreen extends BlockEntity{ int idxToRemove = -1; IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); - for(int i = 0; i < scr.upgrades.size(); i++) { - if(itemAsUpgrade.isSameUpgrade(is, scr.upgrades.get(i))) { + for (int i = 0; i < scr.upgrades.size(); i++) { + if (itemAsUpgrade.isSameUpgrade(is, scr.upgrades.get(i))) { idxToRemove = i; break; } } - if(idxToRemove >= 0) { + if (idxToRemove >= 0) { dropUpgrade(scr.upgrades.get(idxToRemove), side, player); scr.upgrades.remove(idxToRemove); Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.upgrade(this, side)); @@ -925,19 +948,19 @@ public class TileEntityScreen extends BlockEntity{ } private void dropUpgrade(ItemStack is, BlockSide side, @Nullable Player ply) { - if(!((IUpgrade) is.getItem()).onRemove(this, side, ply, is)) { //Drop upgrade item + if (!((IUpgrade) is.getItem()).onRemove(this, side, ply, is)) { //Drop upgrade item boolean spawnDrop = true; - if(ply != null) { - if(ply.isCreative() || ply.addItem(is)) + if (ply != null) { + if (ply.isCreative() || ply.addItem(is)) spawnDrop = false; //If in creative or if the item was added to the player's inventory, don't spawn drop entity } - if(spawnDrop) { + if (spawnDrop) { Vector3f pos = new Vector3f((float) this.getBlockPos().getX(), (float) this.getBlockPos().getY(), (float) this.getBlockPos().getZ()); pos.addMul(side.backward.toFloat(), 1.5f); - if(level != null) { + if (level != null) { level.addFreshEntity(new ItemEntity(level, pos.x, pos.y, pos.z, is)); } } @@ -945,19 +968,19 @@ public class TileEntityScreen extends BlockEntity{ } private Screen getScreenForLaserOp(BlockSide side, Player ply) { - if(level.isClientSide) + if (level.isClientSide) return null; Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Called laser operation on invalid screen on side %s", side.toString()); return null; } - if((scr.rightsFor(ply) & ScreenRights.CLICK) == 0) + if ((scr.rightsFor(ply) & ScreenRights.CLICK) == 0) return null; //Don't output an error, it can 'legally' happen - if(scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matches)) { + if (scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matches)) { Log.error("Called laser operation on side %s, but it's missing the laser sensor upgrade", side.toString()); return null; } @@ -968,14 +991,14 @@ public class TileEntityScreen extends BlockEntity{ public void laserDownMove(BlockSide side, Player ply, Vector2i pos, boolean down) { Screen scr = getScreenForLaserOp(side, ply); - if(scr != null) { - if(down) { + if (scr != null) { + if (down) { //Try to acquire laser lock - if(getLaserUser(scr) == null) { + if (getLaserUser(scr) == null) { scr.laserUser = ply; Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.click(this, side, CMessageScreenUpdate.MOUSE_DOWN, pos)); } - } else if(getLaserUser(scr) == ply) + } else if (getLaserUser(scr) == ply) Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.click(this, side, CMessageScreenUpdate.MOUSE_MOVE, pos)); } } @@ -983,8 +1006,8 @@ public class TileEntityScreen extends BlockEntity{ public void laserUp(BlockSide side, Player ply) { Screen scr = getScreenForLaserOp(side, ply); - if(scr != null) { - if(getLaserUser(scr) == ply) { + if (scr != null) { + if (getLaserUser(scr) == ply) { scr.laserUser = null; Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.click(this, side, CMessageScreenUpdate.MOUSE_UP, null)); } @@ -992,7 +1015,7 @@ public class TileEntityScreen extends BlockEntity{ } public void onDestroy(@Nullable Player ply) { - for(Screen scr: screens) { + for (Screen scr : screens) { scr.upgrades.forEach(is -> dropUpgrade(is, scr.side, ply)); scr.upgrades.clear(); } @@ -1001,18 +1024,18 @@ public class TileEntityScreen extends BlockEntity{ } public void setOwner(BlockSide side, Player newOwner) { - if(level.isClientSide) { + if (level.isClientSide) { Log.error("Called TileEntityScreen.setOwner() on client..."); return; } - if(newOwner == null) { + if (newOwner == null) { Log.error("Called TileEntityScreen.setOwner() with null owner"); return; } Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Called TileEntityScreen.setOwner() on invalid screen on side %s", side.toString()); return; } @@ -1025,18 +1048,18 @@ public class TileEntityScreen extends BlockEntity{ public void setRotation(BlockSide side, Rotation rot) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Trying to change rotation of invalid screen on side %s", side.toString()); return; } - if(level.isClientSide) { + if (level.isClientSide) { boolean oldWasVertical = scr.rotation.isVertical; scr.rotation = rot; WebDisplays.PROXY.screenUpdateRotationInGui(new Vector3i(getBlockPos()), side, rot); - if(scr.browser != null && oldWasVertical != rot.isVertical) { + if (scr.browser != null && oldWasVertical != rot.isVertical) { scr.browser.close(); scr.browser = null; //Will be re-created by renderer } @@ -1049,13 +1072,13 @@ public class TileEntityScreen extends BlockEntity{ public void evalJS(BlockSide side, String code) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Trying to run JS code on invalid screen on side %s", side.toString()); return; } - if(level.isClientSide) { - if(scr.browser != null) + if (level.isClientSide) { + if (scr.browser != null) scr.browser.runJS(code, ""); } else Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.js(this, side, code)); @@ -1063,14 +1086,14 @@ public class TileEntityScreen extends BlockEntity{ public void setAutoVolume(BlockSide side, boolean av) { Screen scr = getScreen(side); - if(scr == null) { + if (scr == null) { Log.error("Trying to toggle auto-volume on invalid screen (side %s)", side.toString()); return; } scr.autoVolume = av; - if(level.isClientSide) + if (level.isClientSide) WebDisplays.PROXY.screenUpdateAutoVolumeInGui(new Vector3i(getBlockPos()), side, av); else { Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), CMessageScreenUpdate.autoVolume(this, side, av)); diff --git a/src/main/java/net/montoyo/wd/net/client/CMessageAddScreen.java b/src/main/java/net/montoyo/wd/net/client/CMessageAddScreen.java index 1b52389..f4cae6d 100644 --- a/src/main/java/net/montoyo/wd/net/client/CMessageAddScreen.java +++ b/src/main/java/net/montoyo/wd/net/client/CMessageAddScreen.java @@ -13,6 +13,7 @@ import net.montoyo.wd.WebDisplays; import net.montoyo.wd.entity.TileEntityScreen; import net.montoyo.wd.utilities.*; +import java.io.IOException; import java.util.ArrayList; import java.util.function.Supplier; @@ -104,12 +105,20 @@ public class CMessageAddScreen { for (TileEntityScreen.Screen entry : screens) { TileEntityScreen.Screen scr = tes.addScreen(entry.side, entry.size, entry.resolution, null, false); scr.rotation = entry.rotation; - scr.url = entry.url; + String webUrl; + + try { + webUrl = TileEntityScreen.url(entry.url); + } catch (IOException e) { + throw new RuntimeException(e); + } + + scr.url = webUrl; scr.owner = entry.owner; scr.upgrades = entry.upgrades; if (scr.browser != null) - scr.browser.loadURL(entry.url); + scr.browser.loadURL(webUrl); } }); diff --git a/src/main/java/net/montoyo/wd/net/client/CMessageScreenUpdate.java b/src/main/java/net/montoyo/wd/net/client/CMessageScreenUpdate.java index 9bf0160..c9e05d7 100644 --- a/src/main/java/net/montoyo/wd/net/client/CMessageScreenUpdate.java +++ b/src/main/java/net/montoyo/wd/net/client/CMessageScreenUpdate.java @@ -17,6 +17,7 @@ import net.montoyo.wd.init.BlockInit; import net.montoyo.wd.utilities.*; import javax.annotation.Nullable; +import java.io.IOException; import java.util.ArrayList; import java.util.function.Supplier; @@ -252,7 +253,13 @@ public class CMessageScreenUpdate { TileEntityScreen tes = (TileEntityScreen) te; switch (action) { - case UPDATE_URL -> tes.setScreenURL(side, string); + case UPDATE_URL -> { + try { + tes.setScreenURL(side, string); + } catch (IOException e) { + throw new RuntimeException(e); + } + } case UPDATE_MOUSE -> tes.handleMouseEvent(side, mouseEvent, vec2i); case UPDATE_DELETE -> tes.removeScreen(side); case UPDATE_RESOLUTION -> tes.setResolution(side, vec2i); diff --git a/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java b/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java index 2150c2b..4fcad1d 100644 --- a/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java +++ b/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java @@ -24,6 +24,7 @@ import net.montoyo.wd.init.BlockInit; import net.montoyo.wd.init.ItemInit; import net.montoyo.wd.utilities.*; +import java.io.IOException; import java.util.function.Supplier; public class SMessageScreenCtrl implements Runnable { @@ -309,7 +310,11 @@ public class SMessageScreenCtrl implements Runnable { if(ctrl == CTRL_SET_URL || ctrl == CTRL_SET_URL_REMOTE) { checkPermission(tes, ScreenRights.CHANGE_URL); - tes.setScreenURL(side, url); + try { + tes.setScreenURL(side, url); + } catch (IOException e) { + throw new RuntimeException(e); + } } else if(ctrl == CTRL_SHUT_DOWN) { //TODO //checkPermission(tes, ScreenRights.CHANGE_URL);