From f7f92cd19c709e1ecbb9c6b80a69e76c3eb8d83f Mon Sep 17 00:00:00 2001 From: GiantLuigi4 <49770992+GiantLuigi4@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:56:23 -0400 Subject: [PATCH] lot of the work is done --- build.gradle | 5 +- libs/mcef-2.x.jar | Bin 0 -> 195086 bytes .../montoyo/wd/block/BlockKeyboardRight.java | 3 +- .../net/montoyo/wd/block/BlockPeripheral.java | 6 +- .../net/montoyo/wd/client/ClientProxy.java | 6 +- .../montoyo/wd/client/JSQueryDispatcher.java | 742 +++--- .../montoyo/wd/client/gui/GuiKeyboard.java | 4 +- .../wd/client/gui/GuiRedstoneCtrl.java | 25 +- .../wd/client/gui/controls/Control.java | 19 +- .../renderers/LaserPointerRenderer.java | 22 +- .../wd/client/renderers/MinePadRenderer.java | 29 +- .../wd/client/renderers/ModelMinePad.java | 2 +- .../wd/client/renderers/ScreenRenderer.java | 9 +- .../java/net/montoyo/wd/core/Criterion.java | 5 +- .../montoyo/wd/core/IScreenQueryHandler.java | 38 +- .../montoyo/wd/entity/TileEntityScreen.java | 2304 +++++++++-------- .../java/net/montoyo/wd/init/BlockInit.java | 4 +- .../net/montoyo/wd/item/ItemLaserPointer.java | 3 +- .../net/montoyo/wd/utilities/VideoType.java | 8 +- 19 files changed, 1624 insertions(+), 1610 deletions(-) create mode 100644 libs/mcef-2.x.jar diff --git a/build.gradle b/build.gradle index b0eef22..f9c4da4 100644 --- a/build.gradle +++ b/build.gradle @@ -71,17 +71,18 @@ repositories{ url = "https://www.cursemaven.com" } flatDir { dirs 'libs' } + maven { url 'https://mcef-download.cinemamod.com/repository/releases' } } dependencies { minecraft 'net.neoforged:forge:1.20.1-47.1.65' annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' - + // implementation fg.deobf("com.github.Mysticpasta1:mcef-forge:2ec6581622") // implementation fg.deobf("curse.maven:SU-370704:4485052") // implementation fg.deobf("curse.maven:spark-361579:4381167") -// implementation fg.deobf("flatdir.lib:mcef:1.2.4") + implementation fg.deobf("flatdir.lib:mcef:2.x") // implementation fg.deobf("flatdir.lib:smallerunits:2.1.3") // compileOnly fg.deobf("curse.maven:vivecraft-667903:4409427") diff --git a/libs/mcef-2.x.jar b/libs/mcef-2.x.jar new file mode 100644 index 0000000000000000000000000000000000000000..05180058413e53644f2c53046445841e9906dadf GIT binary patch literal 195086 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 queue = new ArrayDeque<>(); - private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair(); - private final HashMap handlers = new HashMap<>(); - private final ArrayList serverQueries = new ArrayList<>(); - private final Minecraft mc = Minecraft.getInstance(); - - public JSQueryDispatcher(ClientProxy proxy) { - this.proxy = proxy; - registerDefaults(); - } - - public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) { - synchronized(queue) { - queue.offer(new QueryData(b, q, a, cb)); - } - } - - public void handleQueries() { - while(true) { - QueryData next; - synchronized(queue) { - next = queue.poll(); - } - - if(next == null) - break; - - if(proxy.findScreenFromBrowser(next.browser, lookupResult)) { - Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args); - - if(args == null) - next.callback.failure(400, "Malformed request parameters"); - else { - try { - handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args); - } catch(Throwable t) { - Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args); - next.callback.failure(500, "Internal error"); - } - } - } else - next.callback.failure(403, "A screen is required"); - } - } - - public boolean canHandleQuery(String q) { - return handlers.containsKey(q); - } - - private static Object[] parseArgs(String args) { - ArrayList array = new ArrayList<>(); - int lastIdx = 0; - boolean inString = false; - boolean escape = false; - boolean hadString = false; - - for(int i = 0; i < args.length(); i++) { - char chr = args.charAt(i); - - if(inString) { - if(escape) - escape = false; - else { - if(chr == '\"') - inString = false; - else if(chr == '\\') - escape = true; - } - } else if(chr == '\"') { - if(hadString) - return null; - - inString = true; - hadString = true; - } else if(chr == ',') { - array.add(args.substring(lastIdx, i).trim()); - lastIdx = i + 1; - hadString = false; - } - } - - if(inString) - return null; //Non terminated string - - array.add(args.substring(lastIdx).trim()); - Object[] ret = new Object[array.size()]; - - for(int i = 0; i < ret.length; i++) { - String str = array.get(i); - if(str.isEmpty()) - return null; //Nah... - - if(str.charAt(0) == '\"') //String - ret[i] = str.substring(1, str.length() - 1); - else { - try { - ret[i] = Double.parseDouble(str); - } catch(NumberFormatException ex) { - return null; - } - } - } - - return ret; - } - - public void register(String query, IScreenQueryHandler handler) { - handlers.put(query.toLowerCase(), handler); - } - - public ServerQuery fulfillQuery(int id) { - int toRemove = -1; - - for(int i = 0; i < serverQueries.size(); i++) { - ServerQuery sq = serverQueries.get(i); - - if(sq.id == id) { - toRemove = i; - break; - } - } - - if(toRemove < 0) - return null; - else - return serverQueries.remove(toRemove); - } - - private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) { - ServerQuery ret = new ServerQuery(tes, side, cb); - serverQueries.add(ret); - - WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data)); - } - - private void registerDefaults() { - VideoType.registerQueries(this); - - register("GetSize", (cb, tes, side, args) -> { - Vector2i size = tes.getScreen(side).size; - cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}"); - }); - - register("GetRedstoneAt", (cb, tes, side, args) -> { - if(!tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) { - cb.failure(403, "Missing upgrade"); - return; - } - - if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) { - TileEntityScreen.Screen scr = tes.getScreen(side); - int x = ((Double) args[0]).intValue(); - int y = ((Double) args[1]).intValue(); - - if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) - cb.failure(403, "Out of range"); - else { - BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock(); - int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]); - cb.success("{\"level\":" + level + "}"); - } - } else - cb.failure(400, "Wrong arguments"); - }); - - register("GetRedstoneArray", (cb, tes, side, args) -> { - if(tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) { - final Direction facing = Direction.values()[side.reverse().ordinal()]; - final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}"); - - tes.forEachScreenBlocks(side, bp -> { - if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting)) - resp.add("0"); - else - resp.add("" + tes.getLevel().getSignal(bp, facing)); - }); - - cb.success(resp.toString()); - } else - cb.failure(403, "Missing upgrade"); - }); - - register("ClearRedstone", (cb, tes, side, args) -> { - if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { - if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) - makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE); - else - cb.success("{\"status\":\"notOwner\"}"); - } else - cb.failure(403, "Missing upgrade"); - }); - - register("SetRedstoneAt", (cb, tes, side, args) -> { - if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) { - cb.failure(400, "Wrong arguments"); - return; - } - - if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { - cb.failure(403, "Missing upgrade"); - return; - } - - if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) { - cb.success("{\"status\":\"notOwner\"}"); - return; - } - - int x = ((Double) args[0]).intValue(); - int y = ((Double) args[1]).intValue(); - boolean state = ((Double) args[2]) > 0.0; - - Vector2i size = tes.getScreen(side).size; - if(x < 0 || x >= size.x || y < 0 || y >= size.y) { - cb.failure(403, "Out of range"); - return; - } - - makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state); - }); - - register("IsEmitting", (cb, tes, side, args) -> { - if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { - cb.failure(403, "Missing upgrade"); - return; - } - - if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) { - TileEntityScreen.Screen scr = tes.getScreen(side); - int x = ((Double) args[0]).intValue(); - int y = ((Double) args[1]).intValue(); - - if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) - cb.failure(403, "Out of range"); - else { - BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock(); - boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting); - cb.success("{\"emitting\":" + (e ? "true" : "false") + "}"); - } - } else - cb.failure(400, "Wrong arguments"); - }); - - register("GetEmissionArray", (cb, tes, side, args) -> { - if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { - final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}"); - tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0")); - cb.success(resp.toString()); - } else - cb.failure(403, "Missing upgrade"); - }); - - register("GetLocation", (cb, tes, side, args) -> { - if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) { - cb.failure(403, "Missing upgrade"); - return; - } - - BlockPos bp = tes.getBlockPos(); - cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}"); - }); - - register("GetUpgrades", (cb, tes, side, args) -> { - final StringBuilder sb = new StringBuilder("{\"upgrades\":["); - final ArrayList upgrades = tes.getScreen(side).upgrades; - - for(int i = 0; i < upgrades.size(); i++) { - if(i > 0) - sb.append(','); - - sb.append('\"'); - sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i)))); - sb.append('\"'); - } - - cb.success(sb.append("]}").toString()); - }); - - register("IsOwner", (cb, tes, side, args) -> { - boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())); - cb.success("{\"isOwner\":" + (res ? "true}" : "false}")); - }); - - register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}")); - register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}")); - } - -} +///* +// * Copyright (C) 2018 BARBOTIN Nicolas +// */ +// +//package net.montoyo.wd.client; +// +//import net.minecraft.client.Minecraft; +//import net.minecraft.core.BlockPos; +//import net.minecraft.core.Direction; +//import net.minecraft.world.item.ItemStack; +//import net.minecraftforge.api.distmarker.Dist; +//import net.minecraftforge.api.distmarker.OnlyIn; +//import net.montoyo.wd.block.BlockScreen; +//import net.montoyo.wd.core.DefaultUpgrade; +//import net.montoyo.wd.core.IScreenQueryHandler; +//import net.montoyo.wd.core.IUpgrade; +//import net.montoyo.wd.core.JSServerRequest; +//import net.montoyo.wd.entity.TileEntityScreen; +//import net.montoyo.wd.net.WDNetworkRegistry; +//import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl; +//import net.montoyo.wd.utilities.*; +// +//import java.util.*; +// +//@OnlyIn(Dist.CLIENT) +//public final class JSQueryDispatcher { +// +// private static final class QueryData { +// +// private final IBrowser browser; +// private final String query; +// private final String args; +// private final IJSQueryCallback callback; +// +// private QueryData(IBrowser b, String q, String a, IJSQueryCallback cb) { +// browser = b; +// query = q; +// args = a; +// callback = cb; +// } +// +// } +// +// public static final class ServerQuery { +// +// private static int lastId = 0; +// +// private final TileEntityScreen tes; +// private final BlockSide side; +// private final IJSQueryCallback callback; +// private final int id; +// +// private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) { +// tes = t; +// side = s; +// callback = cb; +// id = lastId++; +// } +// +// public TileEntityScreen getTileEntity() { +// return tes; +// } +// +// public BlockSide getSide() { +// return side; +// } +// +// public TileEntityScreen.Screen getScreen() { +// return tes.getScreen(side); +// } +// +// public void success(String resp) { +// callback.success(resp); +// } +// +// public void error(int errId, String errStr) { +// callback.failure(errId, errStr); +// } +// +// } +// +// private final ClientProxy proxy; +// private final ArrayDeque queue = new ArrayDeque<>(); +// private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair(); +// private final HashMap handlers = new HashMap<>(); +// private final ArrayList serverQueries = new ArrayList<>(); +// private final Minecraft mc = Minecraft.getInstance(); +// +// public JSQueryDispatcher(ClientProxy proxy) { +// this.proxy = proxy; +// registerDefaults(); +// } +// +// public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) { +// synchronized(queue) { +// queue.offer(new QueryData(b, q, a, cb)); +// } +// } +// +// public void handleQueries() { +// while(true) { +// QueryData next; +// synchronized(queue) { +// next = queue.poll(); +// } +// +// if(next == null) +// break; +// +// if(proxy.findScreenFromBrowser(next.browser, lookupResult)) { +// Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args); +// +// if(args == null) +// next.callback.failure(400, "Malformed request parameters"); +// else { +// try { +// handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args); +// } catch(Throwable t) { +// Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args); +// next.callback.failure(500, "Internal error"); +// } +// } +// } else +// next.callback.failure(403, "A screen is required"); +// } +// } +// +// public boolean canHandleQuery(String q) { +// return handlers.containsKey(q); +// } +// +// private static Object[] parseArgs(String args) { +// ArrayList array = new ArrayList<>(); +// int lastIdx = 0; +// boolean inString = false; +// boolean escape = false; +// boolean hadString = false; +// +// for(int i = 0; i < args.length(); i++) { +// char chr = args.charAt(i); +// +// if(inString) { +// if(escape) +// escape = false; +// else { +// if(chr == '\"') +// inString = false; +// else if(chr == '\\') +// escape = true; +// } +// } else if(chr == '\"') { +// if(hadString) +// return null; +// +// inString = true; +// hadString = true; +// } else if(chr == ',') { +// array.add(args.substring(lastIdx, i).trim()); +// lastIdx = i + 1; +// hadString = false; +// } +// } +// +// if(inString) +// return null; //Non terminated string +// +// array.add(args.substring(lastIdx).trim()); +// Object[] ret = new Object[array.size()]; +// +// for(int i = 0; i < ret.length; i++) { +// String str = array.get(i); +// if(str.isEmpty()) +// return null; //Nah... +// +// if(str.charAt(0) == '\"') //String +// ret[i] = str.substring(1, str.length() - 1); +// else { +// try { +// ret[i] = Double.parseDouble(str); +// } catch(NumberFormatException ex) { +// return null; +// } +// } +// } +// +// return ret; +// } +// +// public void register(String query, IScreenQueryHandler handler) { +// handlers.put(query.toLowerCase(), handler); +// } +// +// public ServerQuery fulfillQuery(int id) { +// int toRemove = -1; +// +// for(int i = 0; i < serverQueries.size(); i++) { +// ServerQuery sq = serverQueries.get(i); +// +// if(sq.id == id) { +// toRemove = i; +// break; +// } +// } +// +// if(toRemove < 0) +// return null; +// else +// return serverQueries.remove(toRemove); +// } +// +// private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) { +// ServerQuery ret = new ServerQuery(tes, side, cb); +// serverQueries.add(ret); +// +// WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data)); +// } +// +// private void registerDefaults() { +// VideoType.registerQueries(this); +// +// register("GetSize", (cb, tes, side, args) -> { +// Vector2i size = tes.getScreen(side).size; +// cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}"); +// }); +// +// register("GetRedstoneAt", (cb, tes, side, args) -> { +// if(!tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) { +// cb.failure(403, "Missing upgrade"); +// return; +// } +// +// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) { +// TileEntityScreen.Screen scr = tes.getScreen(side); +// int x = ((Double) args[0]).intValue(); +// int y = ((Double) args[1]).intValue(); +// +// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) +// cb.failure(403, "Out of range"); +// else { +// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock(); +// int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]); +// cb.success("{\"level\":" + level + "}"); +// } +// } else +// cb.failure(400, "Wrong arguments"); +// }); +// +// register("GetRedstoneArray", (cb, tes, side, args) -> { +// if(tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) { +// final Direction facing = Direction.values()[side.reverse().ordinal()]; +// final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}"); +// +// tes.forEachScreenBlocks(side, bp -> { +// if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting)) +// resp.add("0"); +// else +// resp.add("" + tes.getLevel().getSignal(bp, facing)); +// }); +// +// cb.success(resp.toString()); +// } else +// cb.failure(403, "Missing upgrade"); +// }); +// +// register("ClearRedstone", (cb, tes, side, args) -> { +// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { +// if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) +// makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE); +// else +// cb.success("{\"status\":\"notOwner\"}"); +// } else +// cb.failure(403, "Missing upgrade"); +// }); +// +// register("SetRedstoneAt", (cb, tes, side, args) -> { +// if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) { +// cb.failure(400, "Wrong arguments"); +// return; +// } +// +// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { +// cb.failure(403, "Missing upgrade"); +// return; +// } +// +// if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) { +// cb.success("{\"status\":\"notOwner\"}"); +// return; +// } +// +// int x = ((Double) args[0]).intValue(); +// int y = ((Double) args[1]).intValue(); +// boolean state = ((Double) args[2]) > 0.0; +// +// Vector2i size = tes.getScreen(side).size; +// if(x < 0 || x >= size.x || y < 0 || y >= size.y) { +// cb.failure(403, "Out of range"); +// return; +// } +// +// makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state); +// }); +// +// register("IsEmitting", (cb, tes, side, args) -> { +// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { +// cb.failure(403, "Missing upgrade"); +// return; +// } +// +// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) { +// TileEntityScreen.Screen scr = tes.getScreen(side); +// int x = ((Double) args[0]).intValue(); +// int y = ((Double) args[1]).intValue(); +// +// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y) +// cb.failure(403, "Out of range"); +// else { +// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock(); +// boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting); +// cb.success("{\"emitting\":" + (e ? "true" : "false") + "}"); +// } +// } else +// cb.failure(400, "Wrong arguments"); +// }); +// +// register("GetEmissionArray", (cb, tes, side, args) -> { +// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) { +// final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}"); +// tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0")); +// cb.success(resp.toString()); +// } else +// cb.failure(403, "Missing upgrade"); +// }); +// +// register("GetLocation", (cb, tes, side, args) -> { +// if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) { +// cb.failure(403, "Missing upgrade"); +// return; +// } +// +// BlockPos bp = tes.getBlockPos(); +// cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}"); +// }); +// +// register("GetUpgrades", (cb, tes, side, args) -> { +// final StringBuilder sb = new StringBuilder("{\"upgrades\":["); +// final ArrayList upgrades = tes.getScreen(side).upgrades; +// +// for(int i = 0; i < upgrades.size(); i++) { +// if(i > 0) +// sb.append(','); +// +// sb.append('\"'); +// sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i)))); +// sb.append('\"'); +// } +// +// cb.success(sb.append("]}").toString()); +// }); +// +// register("IsOwner", (cb, tes, side, args) -> { +// boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())); +// cb.success("{\"isOwner\":" + (res ? "true}" : "false}")); +// }); +// +// register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}")); +// register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}")); +// } +// +//} diff --git a/src/main/java/net/montoyo/wd/client/gui/GuiKeyboard.java b/src/main/java/net/montoyo/wd/client/gui/GuiKeyboard.java index 73c3fd3..9d61b8e 100644 --- a/src/main/java/net/montoyo/wd/client/gui/GuiKeyboard.java +++ b/src/main/java/net/montoyo/wd/client/gui/GuiKeyboard.java @@ -25,8 +25,8 @@ import net.montoyo.wd.utilities.Log; import net.montoyo.wd.utilities.TypeData; import net.montoyo.wd.utilities.Util; import org.lwjgl.glfw.GLFW; -import org.vivecraft.gameplay.VRPlayer; -import org.vivecraft.gameplay.screenhandlers.KeyboardHandler; +//import org.vivecraft.gameplay.VRPlayer; +//import org.vivecraft.gameplay.screenhandlers.KeyboardHandler; import java.io.*; import java.lang.reflect.Method; diff --git a/src/main/java/net/montoyo/wd/client/gui/GuiRedstoneCtrl.java b/src/main/java/net/montoyo/wd/client/gui/GuiRedstoneCtrl.java index f9a64e5..55cbe99 100644 --- a/src/main/java/net/montoyo/wd/client/gui/GuiRedstoneCtrl.java +++ b/src/main/java/net/montoyo/wd/client/gui/GuiRedstoneCtrl.java @@ -7,7 +7,6 @@ package net.montoyo.wd.client.gui; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import net.montoyo.mcef.api.API; import net.montoyo.wd.WebDisplays; import net.montoyo.wd.client.ClientProxy; import net.montoyo.wd.client.gui.controls.Button; @@ -53,18 +52,18 @@ public class GuiRedstoneCtrl extends WDScreen { tfFallingEdge.setText(fallingEdgeURL); } - @GuiSubscribe - public void onClick(Button.ClickEvent ev) { - if(ev.getSource() == btnOk) { - API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF(); - - String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText())); - String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText())); - WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageRedstoneCtrl(pos, rising, falling)); - } - - minecraft.setScreen(null); - } +// @GuiSubscribe +// public void onClick(Button.ClickEvent ev) { +// if(ev.getSource() == btnOk) { +// API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF(); +// +// String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText())); +// String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText())); +// WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageRedstoneCtrl(pos, rising, falling)); +// } +// +// minecraft.setScreen(null); +// } @Override public boolean isForBlock(BlockPos bp, BlockSide side) { 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 6e5bd41..00c33ac 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 @@ -8,7 +8,6 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; -import com.mojang.math.Matrix4f; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.resources.language.I18n; @@ -18,9 +17,9 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.montoyo.wd.client.gui.WDScreen; import net.montoyo.wd.client.gui.loading.JsonOWrapper; import net.montoyo.wd.utilities.Bounds; +import org.joml.Matrix4f; -import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; -import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL11.*; @OnlyIn(Dist.CLIENT) public abstract class Control { @@ -120,7 +119,8 @@ public abstract class Control { int b = color & 0xFF; RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f); - RenderSystem.disableTexture(); +// RenderSystem.disableTexture(); + glDisable(GL_TEXTURE_2D); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); @@ -132,7 +132,8 @@ public abstract class Control { tessellator.end(); RenderSystem.disableBlend(); - RenderSystem.enableTexture();glEnable(GL_TEXTURE_2D); +// RenderSystem.enableTexture(); + glEnable(GL_TEXTURE_2D); } public void fillTexturedRect(PoseStack poseStack, int x, int y, int w, int h, double u1, double v1, double u2, double v2) { @@ -179,7 +180,8 @@ public abstract class Control { int b = color & 0xFF; RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f); - RenderSystem.enableTexture(); +// RenderSystem.enableTexture(); + glEnable(GL_TEXTURE_2D); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); @@ -210,14 +212,15 @@ public abstract class Control { tessellator.end(); RenderSystem.disableBlend(); - RenderSystem.enableTexture(); +// RenderSystem.enableTexture(); + glEnable(GL_TEXTURE_2D); } public PoseStack beginFramebuffer(RenderTarget fbo, float vpW, float vpH) { fbo.bindWrite(true); RenderSystem.backupProjectionMatrix(); - RenderSystem.setProjectionMatrix(Matrix4f.orthographic(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f)); + RenderSystem.setProjectionMatrix(new Matrix4f().ortho(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f), VertexSorting.ORTHOGRAPHIC_Z); PoseStack poseStack = RenderSystem.getModelViewStack(); poseStack.pushPose(); diff --git a/src/main/java/net/montoyo/wd/client/renderers/LaserPointerRenderer.java b/src/main/java/net/montoyo/wd/client/renderers/LaserPointerRenderer.java index c894ddd..176684e 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/LaserPointerRenderer.java +++ b/src/main/java/net/montoyo/wd/client/renderers/LaserPointerRenderer.java @@ -6,8 +6,6 @@ package net.montoyo.wd.client.renderers; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; -import com.mojang.math.Matrix4f; -import com.mojang.math.Vector3f; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.MultiBufferSource; @@ -20,6 +18,10 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.montoyo.wd.client.ClientProxy; import net.montoyo.wd.init.ItemInit; import net.montoyo.wd.item.ItemLaserPointer; +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL11; + +import static com.mojang.math.Axis.*; @OnlyIn(Dist.CLIENT) public final class LaserPointerRenderer implements IItemRenderer { @@ -45,7 +47,8 @@ public final class LaserPointerRenderer implements IItemRenderer { @Override public boolean render(PoseStack poseStack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) { RenderSystem.disableCull(); - RenderSystem.disableTexture(); +// RenderSystem.disableTexture(); + GL11.glDisable(GL11.GL_TEXTURE_2D); RenderSystem.enableDepthTest(); RenderSystem.enableBlend(); @@ -61,12 +64,12 @@ public final class LaserPointerRenderer implements IItemRenderer { poseStack.pushPose(); poseStack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, (float) (0.2f * Math.sin(sqrtSwingProg * PI * 2.0f)), (float) (-0.2f * Math.sin(swingProgress * PI))); poseStack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f); - poseStack.mulPose(Vector3f.YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f)))); - poseStack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f)); - poseStack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f)); - poseStack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -30.0f)); + poseStack.mulPose(YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f)))); + poseStack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f)); + poseStack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f)); + poseStack.mulPose(YP.rotationDegrees(handSideSign * -30.0f)); poseStack.translate(0.0f, 0.2f, 0.0f); - poseStack.mulPose(Vector3f.XP.rotationDegrees(10.0f)); + poseStack.mulPose(XP.rotationDegrees(10.0f)); poseStack.scale(1.0f / 16.0f, 1.0f / 16.0f, 1.0f / 16.0f); var matrix = poseStack.last().pose(); @@ -98,7 +101,8 @@ public final class LaserPointerRenderer implements IItemRenderer { RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); - RenderSystem.enableTexture(); //Fix for shitty minecraft fire +// RenderSystem.enableTexture(); //Fix for shitty minecraft fire + GL11.glEnable(GL11.GL_TEXTURE_2D); RenderSystem.enableCull(); poseStack.popPose(); diff --git a/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java b/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java index bce77f4..9a05cb9 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java +++ b/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java @@ -6,7 +6,6 @@ package net.montoyo.wd.client.renderers; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Vector3f; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -22,6 +21,8 @@ import net.montoyo.wd.client.ClientProxy; import net.montoyo.wd.config.ClientConfig; import net.montoyo.wd.item.ItemMinePad2; +import static com.mojang.math.Axis.*; + @OnlyIn(Dist.CLIENT) public final class MinePadRenderer implements IItemRenderer { private static final float PI = (float) Math.PI; @@ -76,18 +77,18 @@ public final class MinePadRenderer implements IItemRenderer { stack.pushPose(); stack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, 0.2f * sinSqrtSwingProg2, -0.2f * sinSwingProg1); stack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f); - stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f))); - stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f)); - stack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f)); - stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -45.0f)); + stack.mulPose(YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f))); + stack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f)); + stack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f)); + stack.mulPose(YP.rotationDegrees(handSideSign * -45.0f)); if (sideHold) { stack.translate(0.0f, 0.0f, -0.2f); - stack.mulPose(Vector3f.YP.rotationDegrees(20.0f * -handSideSign)); + stack.mulPose(YP.rotationDegrees(20.0f * -handSideSign)); float total = 0.475f; float off = -0.025f; // gotta love magic numbers stack.translate(-(total - off) + (off * handSideSign), -0.1f, 0.0f); - stack.mulPose(Vector3f.ZP.rotationDegrees(1.0f)); + stack.mulPose(ZP.rotationDegrees(1.0f)); } else if (handSideSign >= 0) // right hand stack.translate(-1.065f, 0.0f, 0.0f); else // left hand @@ -113,7 +114,7 @@ public final class MinePadRenderer implements IItemRenderer { stack.translate(0.063f, 0.28f, 0.001f); RenderSystem.setShaderTexture(0, tex); - pd.view.draw(stack, x1, y1, x2, y2); +// pd.view.draw(stack, x1, y1, x2, y2); } } @@ -129,13 +130,13 @@ public final class MinePadRenderer implements IItemRenderer { float tz = -0.4f * sinSwingProg1; stack.translate(handSideSign * (tx + 0.64000005f), ty - 0.6f - equipProgress * 0.6f, tz - 0.71999997f); - stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * 45.0f)); - stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f)); - stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f)); + stack.mulPose(YP.rotationDegrees(handSideSign * 45.0f)); + stack.mulPose(YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f)); + stack.mulPose(ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f)); stack.translate(-handSideSign, 3.6f, 3.5f); - stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * 120.0f)); - stack.mulPose(Vector3f.XP.rotationDegrees(200.0f)); - stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -135.0f)); + stack.mulPose(ZP.rotationDegrees(handSideSign * 120.0f)); + stack.mulPose(XP.rotationDegrees(200.0f)); + stack.mulPose(YP.rotationDegrees(handSideSign * -135.0f)); stack.translate(handSideSign * 5.6f, 0.0f, 0.0f); PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(mc.player); diff --git a/src/main/java/net/montoyo/wd/client/renderers/ModelMinePad.java b/src/main/java/net/montoyo/wd/client/renderers/ModelMinePad.java index bcfa0de..55a170d 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/ModelMinePad.java +++ b/src/main/java/net/montoyo/wd/client/renderers/ModelMinePad.java @@ -6,7 +6,6 @@ package net.montoyo.wd.client.renderers; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; -import com.mojang.math.Matrix4f; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; @@ -15,6 +14,7 @@ import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import org.joml.Matrix4f; @OnlyIn(Dist.CLIENT) public final class ModelMinePad { 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 3ac5367..f49164d 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java +++ b/src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java @@ -4,6 +4,7 @@ package net.montoyo.wd.client.renderers; +import com.cinemamod.mcef.MCEFBrowser; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import net.minecraft.client.renderer.GameRenderer; @@ -14,8 +15,9 @@ import net.montoyo.wd.entity.TileEntityScreen; import net.montoyo.wd.utilities.Vector3f; import net.montoyo.wd.utilities.Vector3i; import org.jetbrains.annotations.NotNull; +import org.lwjgl.opengl.GL11; -import static com.mojang.math.Vector3f.*; +import static com.mojang.math.Axis.*; public class ScreenRenderer implements BlockEntityRenderer { public ScreenRenderer() { @@ -38,7 +40,8 @@ public class ScreenRenderer implements BlockEntityRenderer { return; //Disable lighting - RenderSystem.enableTexture(); +// RenderSystem.enableTexture(); + GL11.glEnable(GL11.GL_TEXTURE_2D); // RenderSystem.disableCull(); RenderSystem.disableBlend(); @@ -118,7 +121,7 @@ public class ScreenRenderer implements BlockEntityRenderer { //TODO: don't use tesselator RenderSystem.enableDepthTest(); RenderSystem.setShader(GameRenderer::getPositionTexColorShader); - RenderSystem._setShaderTexture(0, scr.browser.getTextureID()); + RenderSystem._setShaderTexture(0, ((MCEFBrowser) scr.browser).getRenderer().getTextureID()); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); builder.vertex(poseStack.last().pose(), -sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex(); diff --git a/src/main/java/net/montoyo/wd/core/Criterion.java b/src/main/java/net/montoyo/wd/core/Criterion.java index 660aece..475aba6 100644 --- a/src/main/java/net/montoyo/wd/core/Criterion.java +++ b/src/main/java/net/montoyo/wd/core/Criterion.java @@ -7,6 +7,7 @@ package net.montoyo.wd.core; import com.google.gson.JsonObject; import net.minecraft.advancements.CriterionTrigger; import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance; +import net.minecraft.advancements.critereon.ContextAwarePredicate; import net.minecraft.advancements.critereon.DeserializationContext; import net.minecraft.advancements.critereon.EntityPredicate; import net.minecraft.resources.ResourceLocation; @@ -22,7 +23,7 @@ public class Criterion implements CriterionTrigger { public static class Instance extends AbstractCriterionTriggerInstance { - public Instance(ResourceLocation id, EntityPredicate.Composite arg2) { + public Instance(ResourceLocation id, ContextAwarePredicate arg2) { super(id, arg2); } } @@ -60,7 +61,7 @@ public class Criterion implements CriterionTrigger { @Override public @NotNull Instance createInstance(JsonObject json, DeserializationContext context) { - return new Instance(id, EntityPredicate.Composite.fromJson(json, "instance", context)); + return new Instance(id, EntityPredicate.fromJson(json, "instance", context)); } public void trigger(PlayerAdvancements ply) { diff --git a/src/main/java/net/montoyo/wd/core/IScreenQueryHandler.java b/src/main/java/net/montoyo/wd/core/IScreenQueryHandler.java index 9ffece1..f9b5617 100644 --- a/src/main/java/net/montoyo/wd/core/IScreenQueryHandler.java +++ b/src/main/java/net/montoyo/wd/core/IScreenQueryHandler.java @@ -1,19 +1,19 @@ -/* - * Copyright (C) 2018 BARBOTIN Nicolas - */ - -package net.montoyo.wd.core; - -import net.montoyo.mcef.api.IJSQueryCallback; -import net.montoyo.wd.entity.TileEntityScreen; -import net.montoyo.wd.utilities.BlockSide; - -import javax.annotation.Nonnull; - -public interface IScreenQueryHandler { - - //args is an array of Doubles or Strings - //The screen DOES exist, so scr.getScreen(side) is never null - void handleQuery(@Nonnull IJSQueryCallback cb, @Nonnull TileEntityScreen scr, @Nonnull BlockSide side, @Nonnull Object[] args); - -} +///* +// * Copyright (C) 2018 BARBOTIN Nicolas +// */ +// +//package net.montoyo.wd.core; +// +//import net.montoyo.mcef.api.IJSQueryCallback; +//import net.montoyo.wd.entity.TileEntityScreen; +//import net.montoyo.wd.utilities.BlockSide; +// +//import javax.annotation.Nonnull; +// +//public interface IScreenQueryHandler { +// +// //args is an array of Doubles or Strings +// //The screen DOES exist, so scr.getScreen(side) is never null +// void handleQuery(@Nonnull IJSQueryCallback cb, @Nonnull TileEntityScreen scr, @Nonnull BlockSide side, @Nonnull Object[] args); +// +//} diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java index cd54c5f..96160eb 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java @@ -4,6 +4,8 @@ package net.montoyo.wd.entity; +import com.cinemamod.mcef.MCEF; +import com.cinemamod.mcef.MCEFBrowser; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -22,7 +24,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraftforge.network.PacketDistributor; -import net.montoyo.mcef.api.IBrowser; import net.montoyo.wd.WebDisplays; import net.montoyo.wd.block.BlockScreen; import net.montoyo.wd.client.ClientProxy; @@ -43,6 +44,7 @@ import net.montoyo.wd.net.client_bound.S2CMessageCloseGui; import net.montoyo.wd.net.client_bound.S2CMessageJSResponse; import net.montoyo.wd.net.client_bound.S2CMessageScreenUpdate; import net.montoyo.wd.utilities.*; +import org.cef.browser.CefBrowser; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -56,1157 +58,1163 @@ import java.util.function.Consumer; import static net.montoyo.wd.block.BlockPeripheral.point; 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; - public Vector2i size; - public Vector2i resolution; - public Rotation rotation = Rotation.ROT_0; - public String url; - private VideoType videoType; - public NameUUIDPair owner; - public ArrayList friends; - public int friendRights; - public int otherRights; - public IBrowser browser; - public ArrayList upgrades; - public boolean doTurnOnAnim; - public long turnOnTime; - public Player laserUser; - public final Vector2i lastMousePos = new Vector2i(); - public NibbleArray redstoneStatus; //null on client - public boolean autoVolume = true; - - public int mouseType; - - public static Screen deserialize(CompoundTag tag) { - Screen ret = new Screen(); - ret.side = BlockSide.values()[tag.getByte("Side")]; - ret.size = new Vector2i(tag.getInt("Width"), tag.getInt("Height")); - ret.resolution = new Vector2i(tag.getInt("ResolutionX"), tag.getInt("ResolutionY")); - ret.rotation = Rotation.values()[tag.getByte("Rotation")]; - ret.url = tag.getString("URL"); - ret.videoType = VideoType.getTypeFromURL(ret.url); - - 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 - psy *= 8.f; - - ret.resolution.x = (int) psx; - ret.resolution.y = (int) psy; - } - - if (tag.contains("OwnerName")) { - String name = tag.getString("OwnerName"); - UUID uuid = tag.getUUID("OwnerUUID"); - ret.owner = new NameUUIDPair(name, uuid); - } - - ListTag friends = tag.getList("Friends", 10); - ret.friends = new ArrayList<>(friends.size()); - - 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); - } - - ret.friendRights = tag.getByte("FriendRights"); - ret.otherRights = tag.getByte("OtherRights"); - - ListTag upgrades = tag.getList("Upgrades", 10); - ret.upgrades = new ArrayList<>(); - - for (int i = 0; i < upgrades.size(); i++) - ret.upgrades.add(ItemStack.of(upgrades.getCompound(i))); - - if (tag.contains("AutoVolume")) - ret.autoVolume = tag.getBoolean("AutoVolume"); - - return ret; - } - - public CompoundTag serialize() { - CompoundTag tag = new CompoundTag(); - tag.putByte("Side", (byte) side.ordinal()); - tag.putInt("Width", size.x); - tag.putInt("Height", size.y); - tag.putInt("ResolutionX", resolution.x); - tag.putInt("ResolutionY", resolution.y); - tag.putByte("Rotation", (byte) rotation.ordinal()); - tag.putString("URL", url); - - if (owner == null) - Log.warning("Found TES with NO OWNER!!"); - else { - tag.putString("OwnerName", owner.name); - tag.putUUID("OwnerUUID", owner.uuid); - } - - ListTag list = new ListTag(); - for (NameUUIDPair f : friends) { - CompoundTag nf = new CompoundTag(); - nf.putString("Name", f.name); - nf.putUUID("UUID", f.uuid); - - list.add(nf); - } - - tag.put("Friends", list); - tag.putByte("FriendRights", (byte) friendRights); - tag.putByte("OtherRights", (byte) otherRights); - - list = new ListTag(); - for (ItemStack is : upgrades) - list.add(is.save(new CompoundTag())); - - tag.put("Upgrades", list); - tag.putBoolean("AutoVolume", autoVolume); - return tag; - } - - public int rightsFor(Player ply) { - return rightsFor(ply.getGameProfile().getId()); - } - - public int rightsFor(UUID 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()) { - Log.warning("Called Screen.setupRedstoneStatus() on client."); - return; - } - - if (redstoneStatus != null) { - Log.warning("Called Screen.setupRedstoneStatus() on server, but redstone status is non-null"); - return; - } - - Direction[] VALUES = Direction.values(); - redstoneStatus = new NibbleArray(size.x * size.y); - final Direction facing = VALUES[side.reverse().ordinal()]; - final ScreenIterator it = new ScreenIterator(start, side, size); - - while (it.hasNext()) { - int idx = it.getIndex(); - redstoneStatus.set(idx, world.getSignal(it.next(), facing)); - } - } - - - public void clampResolution() { - if (resolution.x > CommonConfig.Screen.maxResolutionX) { - float newY = ((float) resolution.y) * ((float) CommonConfig.Screen.maxResolutionX) / ((float) resolution.x); - resolution.x = CommonConfig.Screen.maxResolutionX; - resolution.y = (int) newY; - } - - if (resolution.y > CommonConfig.Screen.maxResolutionY) { - float newX = ((float) resolution.x) * ((float) CommonConfig.Screen.maxResolutionY) / ((float) resolution.y); - resolution.x = (int) newX; - resolution.y = CommonConfig.Screen.maxResolutionY; - } - } - - public void createBrowser(boolean doAnim) { - if (WebDisplays.PROXY instanceof ClientProxy clientProxy) { - browser = clientProxy.getMCEF().createBrowser(WebDisplays.applyBlacklist(url != null ? url : "https://www.google.com")); - - if (rotation.isVertical) - browser.resize(resolution.y, resolution.x); - else - browser.resize(resolution.x, resolution.y); - - if (WebDisplays.cursorSupport) - browser.addCursorChangeListener((type) -> mouseType = type); - - doTurnOnAnim = doAnim; - turnOnTime = System.currentTimeMillis(); - } - } - } - - public void forEachScreenBlocks(BlockSide side, Consumer func) { - Screen scr = getScreen(side); - - if (scr != null) { - ScreenIterator it = new ScreenIterator(getBlockPos(), side, scr.size); - - while (it.hasNext()) - func.accept(it.next()); - } - } - - private final ArrayList screens = new ArrayList<>(); - private net.minecraft.world.phys.AABB renderBB = new net.minecraft.world.phys.AABB(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); - private boolean loaded = true; - public float ytVolume = Float.POSITIVE_INFINITY; - - public boolean isLoaded() { - return loaded; - } - - public void load() { - loaded = true; - } - - public void unload() { - for (Screen scr : screens) { - if (scr.browser != null) { - scr.browser.close(); - scr.browser = null; - } - } - - loaded = false; - } - - @Override - public void load(CompoundTag tag) { - super.load(tag); - - ListTag list = tag.getList("WDScreens", Tag.TAG_COMPOUND); - if (list.isEmpty()) - return; - - screens.clear(); - for (int i = 0; i < list.size(); i++) - screens.add(Screen.deserialize(list.getCompound(i))); - } - - @Override - public CompoundTag getUpdateTag() { - CompoundTag tag = new CompoundTag(); - saveAdditional(tag); - return tag; - } - - @Override - public void handleUpdateTag(CompoundTag tag) { - load(tag); - for (Screen screen : screens) { - if (screen.browser == null) screen.createBrowser(false); - if (screen.browser != null) screen.browser.loadURL(screen.url); - } - updateAABB(); - } - - @Override - protected void saveAdditional(CompoundTag tag) { - super.saveAdditional(tag); - - ListTag list = new ListTag(); - for (Screen scr : screens) - list.add(scr.serialize()); - - tag.put("WDScreens", list); - } - - public Screen addScreen(BlockSide side, Vector2i size, @Nullable Vector2i resolution, @Nullable Player owner, boolean sendUpdate) { - for (Screen scr : screens) { - if (scr.side == side) - return scr; - } - - Screen ret = new Screen(); - ret.side = side; - ret.size = size; - ret.url = CommonConfig.Browser.homepage; - ret.friends = new ArrayList<>(); - ret.friendRights = ScreenRights.DEFAULTS; - ret.otherRights = ScreenRights.DEFAULTS; - ret.upgrades = new ArrayList<>(); - - if (owner != null) { - ret.owner = new NameUUIDPair(owner.getGameProfile()); - - 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) - rot = 3; - else if (rot == 3) - rot = 1; - } - - ret.rotation = Rotation.values()[rot]; - } - } - - 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 - psy *= 8.f; - - ret.resolution = new Vector2i((int) psx, (int) psy); - } else - ret.resolution = resolution; - - ret.clampResolution(); - - if (!level.isClientSide) { - ret.setupRedstoneStatus(level, getBlockPos()); - - if (sendUpdate) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageAddScreen(this, ret)); - } - - screens.add(ret); - - if (level.isClientSide) - updateAABB(); - else - setChanged(); + + public TileEntityScreen(BlockPos arg2, BlockState arg3) { + super(TileInit.SCREEN_BLOCK_ENTITY.get(), arg2, arg3); + } + + public static class Screen { + + public BlockSide side; + public Vector2i size; + public Vector2i resolution; + public Rotation rotation = Rotation.ROT_0; + public String url; + private VideoType videoType; + public NameUUIDPair owner; + public ArrayList friends; + public int friendRights; + public int otherRights; + public CefBrowser browser; + public ArrayList upgrades; + public boolean doTurnOnAnim; + public long turnOnTime; + public Player laserUser; + public final Vector2i lastMousePos = new Vector2i(); + public NibbleArray redstoneStatus; //null on client + public boolean autoVolume = true; + + public int mouseType; + + public static Screen deserialize(CompoundTag tag) { + Screen ret = new Screen(); + ret.side = BlockSide.values()[tag.getByte("Side")]; + ret.size = new Vector2i(tag.getInt("Width"), tag.getInt("Height")); + ret.resolution = new Vector2i(tag.getInt("ResolutionX"), tag.getInt("ResolutionY")); + ret.rotation = Rotation.values()[tag.getByte("Rotation")]; + ret.url = tag.getString("URL"); + ret.videoType = VideoType.getTypeFromURL(ret.url); + + 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 + psy *= 8.f; + + ret.resolution.x = (int) psx; + ret.resolution.y = (int) psy; + } + + if (tag.contains("OwnerName")) { + String name = tag.getString("OwnerName"); + UUID uuid = tag.getUUID("OwnerUUID"); + ret.owner = new NameUUIDPair(name, uuid); + } + + ListTag friends = tag.getList("Friends", 10); + ret.friends = new ArrayList<>(friends.size()); + + 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); + } + + ret.friendRights = tag.getByte("FriendRights"); + ret.otherRights = tag.getByte("OtherRights"); + + ListTag upgrades = tag.getList("Upgrades", 10); + ret.upgrades = new ArrayList<>(); + + for (int i = 0; i < upgrades.size(); i++) + ret.upgrades.add(ItemStack.of(upgrades.getCompound(i))); + + if (tag.contains("AutoVolume")) + ret.autoVolume = tag.getBoolean("AutoVolume"); + + return ret; + } + + public CompoundTag serialize() { + CompoundTag tag = new CompoundTag(); + tag.putByte("Side", (byte) side.ordinal()); + tag.putInt("Width", size.x); + tag.putInt("Height", size.y); + tag.putInt("ResolutionX", resolution.x); + tag.putInt("ResolutionY", resolution.y); + tag.putByte("Rotation", (byte) rotation.ordinal()); + tag.putString("URL", url); + + if (owner == null) + Log.warning("Found TES with NO OWNER!!"); + else { + tag.putString("OwnerName", owner.name); + tag.putUUID("OwnerUUID", owner.uuid); + } + + ListTag list = new ListTag(); + for (NameUUIDPair f : friends) { + CompoundTag nf = new CompoundTag(); + nf.putString("Name", f.name); + nf.putUUID("UUID", f.uuid); + + list.add(nf); + } + + tag.put("Friends", list); + tag.putByte("FriendRights", (byte) friendRights); + tag.putByte("OtherRights", (byte) otherRights); + + list = new ListTag(); + for (ItemStack is : upgrades) + list.add(is.save(new CompoundTag())); + + tag.put("Upgrades", list); + tag.putBoolean("AutoVolume", autoVolume); + return tag; + } + + public int rightsFor(Player ply) { + return rightsFor(ply.getGameProfile().getId()); + } + + public int rightsFor(UUID 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()) { + Log.warning("Called Screen.setupRedstoneStatus() on client."); + return; + } + + if (redstoneStatus != null) { + Log.warning("Called Screen.setupRedstoneStatus() on server, but redstone status is non-null"); + return; + } + + Direction[] VALUES = Direction.values(); + redstoneStatus = new NibbleArray(size.x * size.y); + final Direction facing = VALUES[side.reverse().ordinal()]; + final ScreenIterator it = new ScreenIterator(start, side, size); + + while (it.hasNext()) { + int idx = it.getIndex(); + redstoneStatus.set(idx, world.getSignal(it.next(), facing)); + } + } + + + public void clampResolution() { + if (resolution.x > CommonConfig.Screen.maxResolutionX) { + float newY = ((float) resolution.y) * ((float) CommonConfig.Screen.maxResolutionX) / ((float) resolution.x); + resolution.x = CommonConfig.Screen.maxResolutionX; + resolution.y = (int) newY; + } + + if (resolution.y > CommonConfig.Screen.maxResolutionY) { + float newX = ((float) resolution.x) * ((float) CommonConfig.Screen.maxResolutionY) / ((float) resolution.y); + resolution.x = (int) newX; + resolution.y = CommonConfig.Screen.maxResolutionY; + } + } + + public void createBrowser(boolean doAnim) { + if (WebDisplays.PROXY instanceof ClientProxy clientProxy) { + browser = MCEF.createBrowser(WebDisplays.applyBlacklist(url != null ? url : "https://www.google.com"), false); + + if (browser instanceof MCEFBrowser mcefBrowser) { + if (rotation.isVertical) + mcefBrowser.resize(resolution.y, resolution.x); + else + mcefBrowser.resize(resolution.x, resolution.y); + + if (WebDisplays.cursorSupport) + mcefBrowser.setCursorChangeListener((type) -> mouseType = type); + } + + doTurnOnAnim = doAnim; + turnOnTime = System.currentTimeMillis(); + } + } + } + + public void forEachScreenBlocks(BlockSide side, Consumer func) { + Screen scr = getScreen(side); + + if (scr != null) { + ScreenIterator it = new ScreenIterator(getBlockPos(), side, scr.size); + + while (it.hasNext()) + func.accept(it.next()); + } + } + + private final ArrayList screens = new ArrayList<>(); + private net.minecraft.world.phys.AABB renderBB = new net.minecraft.world.phys.AABB(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); + private boolean loaded = true; + public float ytVolume = Float.POSITIVE_INFINITY; + + public boolean isLoaded() { + return loaded; + } + + public void load() { + loaded = true; + } + + public void unload() { + for (Screen scr : screens) { + if (scr.browser != null) { + scr.browser.close(true); + scr.browser = null; + } + } + + loaded = false; + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + + ListTag list = tag.getList("WDScreens", Tag.TAG_COMPOUND); + if (list.isEmpty()) + return; + + screens.clear(); + for (int i = 0; i < list.size(); i++) + screens.add(Screen.deserialize(list.getCompound(i))); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag tag = new CompoundTag(); + saveAdditional(tag); + return tag; + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + load(tag); + for (Screen screen : screens) { + if (screen.browser == null) screen.createBrowser(false); + if (screen.browser != null) screen.browser.loadURL(screen.url); + } + updateAABB(); + } + + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + + ListTag list = new ListTag(); + for (Screen scr : screens) + list.add(scr.serialize()); + + tag.put("WDScreens", list); + } + + public Screen addScreen(BlockSide side, Vector2i size, @Nullable Vector2i resolution, @Nullable Player owner, boolean sendUpdate) { + for (Screen scr : screens) { + if (scr.side == side) + return scr; + } + + Screen ret = new Screen(); + ret.side = side; + ret.size = size; + ret.url = CommonConfig.Browser.homepage; + ret.friends = new ArrayList<>(); + ret.friendRights = ScreenRights.DEFAULTS; + ret.otherRights = ScreenRights.DEFAULTS; + ret.upgrades = new ArrayList<>(); + + if (owner != null) { + ret.owner = new NameUUIDPair(owner.getGameProfile()); + + 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) + rot = 3; + else if (rot == 3) + rot = 1; + } + + ret.rotation = Rotation.values()[rot]; + } + } + + 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 + psy *= 8.f; + + ret.resolution = new Vector2i((int) psx, (int) psy); + } else + ret.resolution = resolution; + + ret.clampResolution(); + + if (!level.isClientSide) { + ret.setupRedstoneStatus(level, getBlockPos()); + + if (sendUpdate) + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageAddScreen(this, ret)); + } + + screens.add(ret); + + if (level.isClientSide) + updateAABB(); + else + setChanged(); // level.blockEntityChanged(worldPosition); - - return ret; - } - - public Screen getScreen(BlockSide side) { - for (Screen scr : screens) { - if (scr.side == side) - return scr; - } - - return null; - } - - public int screenCount() { - return screens.size(); - } - - public Screen getScreen(int idx) { - return screens.get(idx); - } - - public void clear() { - screens.clear(); - - if (!level.isClientSide) - setChanged(); - } - - public void requestData(ServerPlayer ep) { - if (!level.isClientSide) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> ep), new S2CMessageAddScreen(this)); - } - - public static String url(String url) throws IOException { - System.out.println("URL received: " + url); - if (!(WebDisplays.PROXY instanceof ClientProxy)) { - List serverPlayers = WebDisplays.PROXY.getServer().getPlayerList().getPlayers(); - SyncPlugin.syncPlayers(serverPlayers); - for (ServerPlayer serverPlayer : serverPlayers) { - SyncPlugin.setPlayerString(serverPlayer, url); - } - return url; - } else { - return url; // TODO: ? - } - } - - public void setScreenURL(BlockSide side, String url) throws IOException { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Attempt to change URL of non-existing screen on side %s", side.toString()); - return; - } - - String weburl = url(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 { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.setURL(this, side, weburl)); - setChanged(); - } - } - - public void removeScreen(BlockSide side) { - int idx = -1; - for (int i = 0; i < screens.size(); i++) { - if (screens.get(i).side == side) { - idx = i; - break; - } - } - - 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) { - screens.get(idx).browser.close(); - screens.get(idx).browser = null; - } - } else WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageScreenUpdate(this.getBlockPos(), side)); //Delete the screen - - screens.remove(idx); - - 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(); - } - } - - public void setResolution(BlockSide side, Vector2i res) { - 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) { - Log.error("Tried to change resolution of non-existing screen on side %s", side.toString()); - return; - } - - scr.resolution = res; - scr.clampResolution(); - - if (level.isClientSide) { - WebDisplays.PROXY.screenUpdateResolutionInGui(new Vector3i(getBlockPos()), side, res); - - if (scr.browser != null) { - scr.browser.close(); - scr.browser = null; //Will be re-created by renderer - } - } else { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.setResolution(this, side, res)); - setChanged(); - } - } - - private static Player getLaserUser(Screen scr) { - if (scr.laserUser != null) { - if (scr.laserUser.isRemoved() || !scr.laserUser.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemInit.LASER_POINTER.get())) - scr.laserUser = null; - } - - return scr.laserUser; - } - - private static void checkLaserUserRights(Screen scr) { - if (scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.INTERACT) == 0) - scr.laserUser = null; - } - - public void clearLaserUser(BlockSide side) { - Screen scr = getScreen(side); - - if (scr != null) - scr.laserUser = null; - } - - public void click(BlockSide side, Vector2i vec) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Attempt click non-existing screen of side %s", side.toString()); - return; - } - - if (level.isClientSide) - Log.warning("TileEntityScreen.click() from client side is useless..."); - else if (getLaserUser(scr) == null) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.CLICK, vec)); - } - - void clickUnsafe(BlockSide side, ClickControl.ControlType action, int x, int y) { - if (level.isClientSide) { - Vector2i vec = (action == ClickControl.ControlType.UP) ? null : new Vector2i(x, y); - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, action, vec)); - } - } - - public void handleMouseEvent(BlockSide side, ClickControl.ControlType event, @Nullable Vector2i vec, int button) { - if (button > 1) return; // buttons above 1 crash the game - - Screen scr = getScreen(side); - 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 == ClickControl.ControlType.CLICK) { - scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move to target - scr.browser.injectMouseButton(vec.x, vec.y, 0, button, true, 1); //Press - scr.browser.injectMouseButton(vec.x, vec.y, 0, button, false, 1); //Release - } else if (event == ClickControl.ControlType.DOWN) { - scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move to target - scr.browser.injectMouseButton(vec.x, vec.y, 0, button, true, 1); //Press - } else if (event == ClickControl.ControlType.MOVE) - scr.browser.injectMouseMove(vec.x, vec.y, 0, false); //Move - else if (event == ClickControl.ControlType.UP) - scr.browser.injectMouseButton(scr.lastMousePos.x, scr.lastMousePos.y, 0, button, false, 1); //Release - if (vec != null) { - scr.lastMousePos.x = vec.x; - scr.lastMousePos.y = vec.y; - } - } - } - - public void updateJSRedstone(BlockSide side, Vector2i vec, int redstoneLevel) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Called updateJSRedstone on non-existing side %s", side.toString()); - return; - } - - 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) { - scr.setupRedstoneStatus(level, getBlockPos()); - sendMsg = true; - } else { - int idx = vec.y * scr.size.x + vec.x; - - if (scr.redstoneStatus.get(idx) != redstoneLevel) { - scr.redstoneStatus.set(idx, redstoneLevel); - sendMsg = true; - } - } - -// if (sendMsg) -// WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel)); - } - } - - public void handleJSRequest(ServerPlayer src, BlockSide side, int reqId, JSServerRequest req, Object[] data) { - if (level.isClientSide) { - Log.error("Called handleJSRequest client-side"); - return; - } - - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Called handleJSRequest on non-existing side %s", side.toString()); - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Invalid side")); - return; - } - - 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()); - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Only the owner can do that")); - return; - } - - if (scr.upgrades.stream().noneMatch(DefaultUpgrade.REDOUTPUT::matchesRedInput)) { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Missing upgrade")); - return; - } - - 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++) { - vec2.set(vec1); - - for (int x = 0; x < scr.size.x; x++) { - vec2.toBlock(mbp); - - BlockState bs = level.getBlockState(mbp); - 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); - } - - vec1.add(side.up.x, side.up.y, side.up.z); - } - - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, new byte[0])); - } 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) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(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)) - level.setBlockAndUpdate(bp, bs.setValue(BlockScreen.emitting, state)); - - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, new byte[0])); - } - } else - WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 400, "Invalid request")); - } - - @Override - public void onLoad() { - if (level.isClientSide) { - WebDisplays.PROXY.trackScreen(this, true); - } - } - - @Override - public void onChunkUnloaded() { - if (level.isClientSide) { - WebDisplays.PROXY.trackScreen(this, false); - - for (Screen scr : screens) { - if (scr.browser != null) { - scr.browser.close(); - scr.browser = null; - } - } - } - } - - private void updateAABB() { - Vector3i origin = new Vector3i(getBlockPos()); - MutableAABB box = null; - - for (Screen scr : screens) { - Vector3i f = scr.side.forward; - - int fx = Math.max(f.x, 0); - int fy = Math.max(f.y, 0); - int fz = Math.max(f.z, 0); - int ox = 0; - if (scr.side.equals(BlockSide.NORTH)) ox = 1; - int oz = 0; - if ( - scr.side.equals(BlockSide.EAST) || - scr.side.equals(BlockSide.TOP) || - scr.side.equals(BlockSide.BOTTOM) - ) oz = 1; - - if (box == null) { - box = new MutableAABB( - origin.x + fx + ox, - origin.y + fy, - origin.z + fz + oz, - - origin.x + ox + scr.side.right.x * scr.size.x + fx + scr.side.up.x * scr.size.y, - origin.y + scr.side.right.y * scr.size.x + fy + scr.side.up.y * scr.size.y, - origin.z + oz + scr.side.right.z * scr.size.x + fz + scr.side.up.z * scr.size.y - ); - } else { - box.expand( - origin.x + fx + ox, - origin.y + fy, - origin.z + fz + oz, - - origin.x + ox + scr.side.right.x * scr.size.x + fx + scr.side.up.x * scr.size.y, - origin.y + scr.side.right.y * scr.size.x + fy + scr.side.up.y * scr.size.y, - origin.z + oz + scr.side.right.z * scr.size.x + fz + scr.side.up.z * scr.size.y - ); - } - } - - if (box == null) renderBB = new AABB(worldPosition); - else renderBB = box.toMc(); - } - - @Override - @Nonnull - public net.minecraft.world.phys.AABB getRenderBoundingBox() { - return renderBB; - } - - //FIXME: Not called if enableSoundDistance is false - public void updateTrackDistance(double d, float masterVolume) { - final WebDisplays wd = WebDisplays.INSTANCE; - boolean needsComputation = true; - 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) { - float dist = (float) Math.sqrt(d); - float vol; - - if (dist <= wd.avDist100) - vol = masterVolume * wd.ytVolume; - 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) - return; //Delta is too small - - ytVolume = vol; - intPart = (int) vol; //Manually convert to string, probably faster in that case... - fracPart = ((int) (vol * 100.0f)) - intPart * 100; - needsComputation = false; - } - - scr.browser.runJS(scr.videoType.getVolumeJSQuery(intPart, fracPart), ""); - } - } - } - - public void updateClientSideURL(IBrowser target, String url) { - for (Screen scr : screens) { - if (scr.browser == target) { - String webUrl; - try { - webUrl = TileEntityScreen.url(url); - } catch (IOException e) { - throw new RuntimeException(e); - } - 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) - scr.browser.loadURL(WebDisplays.BLACKLIST_URL); - - break; - } - } - } - - @Override - public void invalidateCaps() { - super.invalidateCaps(); - - if (level.isClientSide) - onChunkUnloaded(); - } - - public void addFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { - if (!level.isClientSide) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to add friend to invalid screen side %s", side.toString()); - return; - } - - if (!scr.friends.contains(pair)) { - scr.friends.add(pair); - (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); - setChanged(); - } - } - } - - public void removeFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { - if (!level.isClientSide) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to remove friend from invalid screen side %s", side.toString()); - return; - } - - if (scr.friends.remove(pair)) { - checkLaserUserRights(scr); - (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); - setChanged(); - } - } - } - - public void setRights(ServerPlayer ply, BlockSide side, int fr, int or) { - if (!level.isClientSide) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to change rights of invalid screen on side %s", side.toString()); - return; - } - - scr.friendRights = fr; - scr.otherRights = or; - - checkLaserUserRights(scr); - (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); - setChanged(); - } - } - - public void type(BlockSide side, String text, BlockPos soundPos) { - type(side, text, soundPos, null); - } - - public void type(BlockSide side, String text, BlockPos soundPos, @Nullable ServerPlayer sender) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to type on invalid screen on side %s", side.toString()); - return; - } - - if (level.isClientSide) { - if (scr.browser != null) { - try { - if (text.startsWith("t")) { - for (int i = 1; i < text.length(); i++) { - char chr = text.charAt(i); - if (chr == 1) - break; - - scr.browser.injectKeyTyped(chr, 0); - } - } else { - TypeData[] data = WebDisplays.GSON.fromJson(text, TypeData[].class); - - for (TypeData ev : data) { - if (ev.getKeyCode() == 257) { - ev = new TypeData( - ev.getAction(), - 10, ev.getModifier() - ); - } - - switch (ev.getAction()) { - case PRESS -> { - scr.browser.injectKeyPressedByKeyCode(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); - if (ev.getKeyCode() == 10) - scr.browser.injectKeyTyped('\r', 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) { - Log.warningEx("Suspicious keyboard type packet received...", t); - } - } - } else { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with( - sender != null ? - () -> point(sender, level, getBlockPos()) : - () -> point(level, getBlockPos()) - ), S2CMessageScreenUpdate.type(this, side, text)); - - if (soundPos != null) - playSoundAt(WebDisplays.INSTANCE.soundTyping, soundPos, 0.25f, 1.f); - } - } - - private void playSoundAt(SoundEvent snd, BlockPos at, float vol, float pitch) { - double x = at.getX(); - double y = at.getY(); - double z = at.getZ(); - - level.playSound(null, x + 0.5, y + 0.5, z + 0.5, snd, SoundSource.BLOCKS, vol, pitch); - } - - public void updateUpgrades(BlockSide side, ItemStack[] upgrades) { - if (!level.isClientSide) { - Log.error("Tried to call TileEntityScreen.updateUpgrades() from server side..."); - return; - } - - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to update upgrades on invalid screen on side %s", side.toString()); - return; - } - - scr.upgrades.clear(); - Collections.addAll(scr.upgrades, upgrades); - - if (scr.browser != null) - scr.browser.runJS("if(typeof webdisplaysUpgradesChanged == \"function\") webdisplaysUpgradesChanged();", ""); - } - - private static String safeName(ItemStack is) { - return is.getItem().getName(is).getString(); - } - - //If equal is null, no duplicate check is preformed - public boolean addUpgrade(BlockSide side, ItemStack is, @Nullable Player player, boolean abortIfExisting) { - if (level.isClientSide) { - IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); - Screen scr = getScreen(side); + + return ret; + } + + public Screen getScreen(BlockSide side) { + for (Screen scr : screens) { + if (scr.side == side) + return scr; + } + + return null; + } + + public int screenCount() { + return screens.size(); + } + + public Screen getScreen(int idx) { + return screens.get(idx); + } + + public void clear() { + screens.clear(); + + if (!level.isClientSide) + setChanged(); + } + + public void requestData(ServerPlayer ep) { + if (!level.isClientSide) + WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> ep), new S2CMessageAddScreen(this)); + } + + public static String url(String url) throws IOException { + System.out.println("URL received: " + url); + if (!(WebDisplays.PROXY instanceof ClientProxy)) { + List serverPlayers = WebDisplays.PROXY.getServer().getPlayerList().getPlayers(); + SyncPlugin.syncPlayers(serverPlayers); + for (ServerPlayer serverPlayer : serverPlayers) { + SyncPlugin.setPlayerString(serverPlayer, url); + } + return url; + } else { + return url; // TODO: ? + } + } + + public void setScreenURL(BlockSide side, String url) throws IOException { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Attempt to change URL of non-existing screen on side %s", side.toString()); + return; + } + + String weburl = url(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 { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.setURL(this, side, weburl)); + setChanged(); + } + } + + public void removeScreen(BlockSide side) { + int idx = -1; + for (int i = 0; i < screens.size(); i++) { + if (screens.get(i).side == side) { + idx = i; + break; + } + } + + 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) { + screens.get(idx).browser.close(true); + screens.get(idx).browser = null; + } + } else + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageScreenUpdate(this.getBlockPos(), side)); //Delete the screen + + screens.remove(idx); + + 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(); + } + } + + public void setResolution(BlockSide side, Vector2i res) { + 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) { + Log.error("Tried to change resolution of non-existing screen on side %s", side.toString()); + return; + } + + scr.resolution = res; + scr.clampResolution(); + + if (level.isClientSide) { + WebDisplays.PROXY.screenUpdateResolutionInGui(new Vector3i(getBlockPos()), side, res); + + if (scr.browser != null) { + scr.browser.close(true); + scr.browser = null; //Will be re-created by renderer + } + } else { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.setResolution(this, side, res)); + setChanged(); + } + } + + private static Player getLaserUser(Screen scr) { + if (scr.laserUser != null) { + if (scr.laserUser.isRemoved() || !scr.laserUser.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemInit.LASER_POINTER.get())) + scr.laserUser = null; + } + + return scr.laserUser; + } + + private static void checkLaserUserRights(Screen scr) { + if (scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.INTERACT) == 0) + scr.laserUser = null; + } + + public void clearLaserUser(BlockSide side) { + Screen scr = getScreen(side); + + if (scr != null) + scr.laserUser = null; + } + + public void click(BlockSide side, Vector2i vec) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Attempt click non-existing screen of side %s", side.toString()); + return; + } + + if (level.isClientSide) + Log.warning("TileEntityScreen.click() from client side is useless..."); + else if (getLaserUser(scr) == null) + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.CLICK, vec)); + } + + void clickUnsafe(BlockSide side, ClickControl.ControlType action, int x, int y) { + if (level.isClientSide) { + Vector2i vec = (action == ClickControl.ControlType.UP) ? null : new Vector2i(x, y); + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, action, vec)); + } + } + + public void handleMouseEvent(BlockSide side, ClickControl.ControlType event, @Nullable Vector2i vec, int button) { + if (button > 1) return; // buttons above 1 crash the game + + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Attempt inject mouse events on non-existing screen of side %s", side.toString()); + return; + } + + if (scr.browser != null) { + if (scr.browser instanceof MCEFBrowser mcefBrowser) { + if (event == ClickControl.ControlType.CLICK) { + mcefBrowser.sendMouseMove(vec.x, vec.y); //Move to target + mcefBrowser.sendMousePress(vec.x, vec.y, button); //Press + mcefBrowser.sendMouseRelease(vec.x, vec.y, button); //Release + } else if (event == ClickControl.ControlType.DOWN) { + mcefBrowser.sendMouseMove(vec.x, vec.y); //Move to target + mcefBrowser.sendMousePress(vec.x, vec.y, button); //Press + } else if (event == ClickControl.ControlType.MOVE) + mcefBrowser.sendMouseMove(vec.x, vec.y); //Move + else if (event == ClickControl.ControlType.UP) + mcefBrowser.sendMouseRelease(scr.lastMousePos.x, scr.lastMousePos.y, button); //Release + } + + if (vec != null) { + scr.lastMousePos.x = vec.x; + scr.lastMousePos.y = vec.y; + } + } + } + +// public void updateJSRedstone(BlockSide side, Vector2i vec, int redstoneLevel) { +// Screen scr = getScreen(side); +// if (scr == null) { +// Log.error("Called updateJSRedstone on non-existing side %s", side.toString()); +// return; +// } +// +// 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) { +// scr.setupRedstoneStatus(level, getBlockPos()); +// sendMsg = true; +// } else { +// int idx = vec.y * scr.size.x + vec.x; +// +// if (scr.redstoneStatus.get(idx) != redstoneLevel) { +// scr.redstoneStatus.set(idx, redstoneLevel); +// sendMsg = true; +// } +// } +// +//// if (sendMsg) +//// WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel)); +// } +// } +// +// public void handleJSRequest(ServerPlayer src, BlockSide side, int reqId, JSServerRequest req, Object[] data) { +// if (level.isClientSide) { +// Log.error("Called handleJSRequest client-side"); +// return; +// } +// +// Screen scr = getScreen(side); +// if (scr == null) { +// Log.error("Called handleJSRequest on non-existing side %s", side.toString()); +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Invalid side")); +// return; +// } +// +// 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()); +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Only the owner can do that")); +// return; +// } +// +// if (scr.upgrades.stream().noneMatch(DefaultUpgrade.REDOUTPUT::matchesRedInput)) { +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 403, "Missing upgrade")); +// return; +// } +// +// 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++) { +// vec2.set(vec1); +// +// for (int x = 0; x < scr.size.x; x++) { +// vec2.toBlock(mbp); +// +// BlockState bs = level.getBlockState(mbp); +// 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); +// } +// +// vec1.add(side.up.x, side.up.y, side.up.z); +// } +// +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, new byte[0])); +// } 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) +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(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)) +// level.setBlockAndUpdate(bp, bs.setValue(BlockScreen.emitting, state)); +// +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, new byte[0])); +// } +// } else +// WDNetworkRegistry.INSTANCE.send(PacketDistributor.PLAYER.with(() -> src), new S2CMessageJSResponse(reqId, req, 400, "Invalid request")); +// } + + @Override + public void onLoad() { + if (level.isClientSide) { + WebDisplays.PROXY.trackScreen(this, true); + } + } + + @Override + public void onChunkUnloaded() { + if (level.isClientSide) { + WebDisplays.PROXY.trackScreen(this, false); + + for (Screen scr : screens) { + if (scr.browser != null) { + scr.browser.close(true); + scr.browser = null; + } + } + } + } + + private void updateAABB() { + Vector3i origin = new Vector3i(getBlockPos()); + MutableAABB box = null; + + for (Screen scr : screens) { + Vector3i f = scr.side.forward; + + int fx = Math.max(f.x, 0); + int fy = Math.max(f.y, 0); + int fz = Math.max(f.z, 0); + int ox = 0; + if (scr.side.equals(BlockSide.NORTH)) ox = 1; + int oz = 0; + if ( + scr.side.equals(BlockSide.EAST) || + scr.side.equals(BlockSide.TOP) || + scr.side.equals(BlockSide.BOTTOM) + ) oz = 1; + + if (box == null) { + box = new MutableAABB( + origin.x + fx + ox, + origin.y + fy, + origin.z + fz + oz, + + origin.x + ox + scr.side.right.x * scr.size.x + fx + scr.side.up.x * scr.size.y, + origin.y + scr.side.right.y * scr.size.x + fy + scr.side.up.y * scr.size.y, + origin.z + oz + scr.side.right.z * scr.size.x + fz + scr.side.up.z * scr.size.y + ); + } else { + box.expand( + origin.x + fx + ox, + origin.y + fy, + origin.z + fz + oz, + + origin.x + ox + scr.side.right.x * scr.size.x + fx + scr.side.up.x * scr.size.y, + origin.y + scr.side.right.y * scr.size.x + fy + scr.side.up.y * scr.size.y, + origin.z + oz + scr.side.right.z * scr.size.x + fz + scr.side.up.z * scr.size.y + ); + } + } + + if (box == null) renderBB = new AABB(worldPosition); + else renderBB = box.toMc(); + } + + @Override + @Nonnull + public net.minecraft.world.phys.AABB getRenderBoundingBox() { + return renderBB; + } + +// //FIXME: Not called if enableSoundDistance is false +// public void updateTrackDistance(double d, float masterVolume) { +// final WebDisplays wd = WebDisplays.INSTANCE; +// boolean needsComputation = true; +// 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) { +// float dist = (float) Math.sqrt(d); +// float vol; +// +// if (dist <= wd.avDist100) +// vol = masterVolume * wd.ytVolume; +// 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) +// return; //Delta is too small +// +// ytVolume = vol; +// intPart = (int) vol; //Manually convert to string, probably faster in that case... +// fracPart = ((int) (vol * 100.0f)) - intPart * 100; +// needsComputation = false; +// } +// +// scr.browser.runJS(scr.videoType.getVolumeJSQuery(intPart, fracPart), ""); +// } +// } +// } + + public void updateClientSideURL(CefBrowser target, String url) { + for (Screen scr : screens) { + if (scr.browser == target) { + String webUrl; + try { + webUrl = TileEntityScreen.url(url); + } catch (IOException e) { + throw new RuntimeException(e); + } + 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) + scr.browser.loadURL(WebDisplays.BLACKLIST_URL); + + break; + } + } + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + + if (level.isClientSide) + onChunkUnloaded(); + } + + public void addFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { + if (!level.isClientSide) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Tried to add friend to invalid screen side %s", side.toString()); + return; + } + + if (!scr.friends.contains(pair)) { + scr.friends.add(pair); + (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); + setChanged(); + } + } + } + + public void removeFriend(ServerPlayer ply, BlockSide side, NameUUIDPair pair) { + if (!level.isClientSide) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Tried to remove friend from invalid screen side %s", side.toString()); + return; + } + + if (scr.friends.remove(pair)) { + checkLaserUserRights(scr); + (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); + setChanged(); + } + } + } + + public void setRights(ServerPlayer ply, BlockSide side, int fr, int or) { + if (!level.isClientSide) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Tried to change rights of invalid screen on side %s", side.toString()); + return; + } + + scr.friendRights = fr; + scr.otherRights = or; + + checkLaserUserRights(scr); + (new ScreenConfigData(new Vector3i(getBlockPos()), side, scr)).updateOnly().sendTo(point(level, getBlockPos())); + setChanged(); + } + } + + public void type(BlockSide side, String text, BlockPos soundPos) { + type(side, text, soundPos, null); + } + + public void type(BlockSide side, String text, BlockPos soundPos, @Nullable ServerPlayer sender) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Tried to type on invalid screen on side %s", side.toString()); + return; + } + + if (level.isClientSide) { + if (scr.browser instanceof MCEFBrowser mcefBrowser) { + try { + if (text.startsWith("t")) { + for (int i = 1; i < text.length(); i++) { + char chr = text.charAt(i); + if (chr == 1) + break; + + mcefBrowser.sendKeyTyped(chr, 0); + } + } else { + TypeData[] data = WebDisplays.GSON.fromJson(text, TypeData[].class); + + for (TypeData ev : data) { + if (ev.getKeyCode() == 257) { + ev = new TypeData( + ev.getAction(), + 10, ev.getModifier() + ); + } + + switch (ev.getAction()) { + case PRESS -> { + mcefBrowser.sendKeyPress(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); + if (ev.getKeyCode() == 10) + mcefBrowser.sendKeyTyped('\r', ev.getModifier()); + } + case RELEASE -> + mcefBrowser.sendKeyRelease(ev.getKeyCode(), (char) ev.getKeyCode(), ev.getModifier()); + case TYPE -> mcefBrowser.sendKeyTyped((char) ev.getKeyCode(), ev.getModifier()); // TODO: check + + default -> throw new RuntimeException("Invalid type action '" + ev.getAction() + '\''); + } + } + } + } catch (Throwable t) { + Log.warningEx("Suspicious keyboard type packet received...", t); + } + } + } else { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with( + sender != null ? + () -> point(sender, level, getBlockPos()) : + () -> point(level, getBlockPos()) + ), S2CMessageScreenUpdate.type(this, side, text)); + + if (soundPos != null) + playSoundAt(WebDisplays.INSTANCE.soundTyping, soundPos, 0.25f, 1.f); + } + } + + private void playSoundAt(SoundEvent snd, BlockPos at, float vol, float pitch) { + double x = at.getX(); + double y = at.getY(); + double z = at.getZ(); + + level.playSound(null, x + 0.5, y + 0.5, z + 0.5, snd, SoundSource.BLOCKS, vol, pitch); + } + +// public void updateUpgrades(BlockSide side, ItemStack[] upgrades) { +// if (!level.isClientSide) { +// Log.error("Tried to call TileEntityScreen.updateUpgrades() from server side..."); +// return; +// } +// +// Screen scr = getScreen(side); +// if (scr == null) { +// Log.error("Tried to update upgrades on invalid screen on side %s", side.toString()); +// return; +// } +// +// scr.upgrades.clear(); +// Collections.addAll(scr.upgrades, upgrades); +// +// if (scr.browser != null) +// scr.browser.runJS("if(typeof webdisplaysUpgradesChanged == \"function\") webdisplaysUpgradesChanged();", ""); +// } + + private static String safeName(ItemStack is) { + return is.getItem().getName(is).getString(); + } + + //If equal is null, no duplicate check is preformed + public boolean addUpgrade(BlockSide side, ItemStack is, @Nullable Player player, boolean abortIfExisting) { + if (level.isClientSide) { + IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); + Screen scr = getScreen(side); // 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 - scr.upgrades.add(isCopy); - itemAsUpgrade.onInstall(this, side, player, isCopy); - return false; - } - - Screen scr = getScreen(side); - 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)) { - 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) { - 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))) - return false; //Upgrade already exists - - ItemStack isCopy = is.copy(); //FIXME: Duct tape fix, because the original stack will be shrinked - isCopy.setCount(1); - - scr.upgrades.add(isCopy); - if (player != null && !player.level.isClientSide) { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.upgrade(this, side, true, is)); - itemAsUpgrade.onInstall(this, side, player, isCopy); - playSoundAt(WebDisplays.INSTANCE.soundUpgradeAdd, getBlockPos(), 1.0f, 1.0f); - } - setChanged(); - return true; - } - - public boolean hasUpgrade(BlockSide side, ItemStack is) { - Screen scr = getScreen(side); - if (scr == null) - return false; - - if (!(is.getItem() instanceof IUpgrade)) - return false; - - IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); - return scr.upgrades.stream().anyMatch(otherStack -> itemAsUpgrade.isSameUpgrade(is, otherStack)); - } - - public boolean hasUpgrade(BlockSide side, DefaultUpgrade du) { - Screen scr = getScreen(side); - if (du == DefaultUpgrade.LASERMOUSE) { - return scr != null && scr.upgrades.stream().anyMatch(du::matchesLaserMouse); - } else if (du == DefaultUpgrade.REDINPUT) { - return scr != null && scr.upgrades.stream().anyMatch(du::matchesRedInput); - } else if (du == DefaultUpgrade.GPS) { - return scr != null && scr.upgrades.stream().anyMatch(du::matchesGps); - } else if (du == DefaultUpgrade.REDOUTPUT) { - return scr != null && scr.upgrades.stream().anyMatch(du::matchesRedOutput); - } else { - return false; - } - } - - public void removeUpgrade(BlockSide side, ItemStack is, @Nullable Player player) { - if (level.isClientSide) - return; - - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Tried to remove an upgrade on invalid screen on side %s", side.toString()); - return; - } - - 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; - } - - 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))) { - idxToRemove = i; - break; - } - } - - if (idxToRemove >= 0) { - dropUpgrade(scr.upgrades.get(idxToRemove), side, player); - scr.upgrades.remove(idxToRemove); - if (player != null && !player.level.isClientSide) { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.upgrade(this, side, false, is)); - playSoundAt(WebDisplays.INSTANCE.soundUpgradeDel, getBlockPos(), 1.0f, 1.0f); - } - setChanged(); - } else - Log.warning("Tried to remove non-existing upgrade %s to screen %s at %s", safeName(is), side.toString(), getBlockPos().toString()); - } - - private void dropUpgrade(ItemStack is, BlockSide side, @Nullable Player ply) { - if (!((IUpgrade) is.getItem()).onRemove(this, side, ply, is)) { //Drop upgrade item - boolean spawnDrop = true; - - 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) { - 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) { - level.addFreshEntity(new ItemEntity(level, pos.x, pos.y, pos.z, is)); - } - } - } - } - - private Screen getScreenForLaserOp(BlockSide side, Player ply) { - if (level.isClientSide) - return null; - - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Called laser operation on invalid screen on side %s", side.toString()); - return null; - } - - if ((scr.rightsFor(ply) & ScreenRights.INTERACT) == 0) - return null; //Don't output an error, it can 'legally' happen - - if (scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matchesLaserMouse)) { - Log.error("Called laser operation on side %s, but it's missing the laser sensor upgrade", side.toString()); - return null; - } - - return scr; //Okay, go for it... - } - - public void laserDownMove(BlockSide side, Player ply, Vector2i pos, boolean down, int button) { - Screen scr = getScreenForLaserOp(side, ply); - - if (scr != null) { - if (button == -1) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.MOVE, pos)); - else if (down) - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.DOWN, pos)); - else - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.UP, pos)); - } - } - - public void laserUp(BlockSide side, Player ply, int button) { - Screen scr = getScreenForLaserOp(side, ply); - - if (scr != null) { - if (getLaserUser(scr) == ply) { - scr.laserUser = null; - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.UP, null)); - } - } - } - - public void onDestroy(@Nullable Player ply) { - for (Screen scr : screens) { - scr.upgrades.forEach(is -> dropUpgrade(is, scr.side, ply)); - scr.upgrades.clear(); - } - - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageCloseGui(getBlockPos())); - } - - public void setOwner(BlockSide side, Player newOwner) { - if (level.isClientSide) { - Log.error("Called TileEntityScreen.setOwner() on client..."); - return; - } - - if (newOwner == null) { - Log.error("Called TileEntityScreen.setOwner() with null owner"); - return; - } - - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Called TileEntityScreen.setOwner() on invalid screen on side %s", side.toString()); - return; - } - - scr.owner = new NameUUIDPair(newOwner.getGameProfile()); - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.owner(this, side, scr.owner)); - checkLaserUserRights(scr); - setChanged(); - } - - public void setRotation(BlockSide side, Rotation rot) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Trying to change rotation of invalid screen on side %s", side.toString()); - return; - } - - 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) { - scr.browser.close(); - scr.browser = null; //Will be re-created by renderer - } - } else { - scr.rotation = rot; - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.rotation(this, side, rot)); - setChanged(); - } - } - - public void evalJS(BlockSide side, String code) { - Screen scr = getScreen(side); - 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) - scr.browser.runJS(code, ""); - } -// else WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.js(this, side, code)); - } - - public void setAutoVolume(BlockSide side, boolean av) { - Screen scr = getScreen(side); - if (scr == null) { - Log.error("Trying to toggle auto-volume on invalid screen (side %s)", side.toString()); - return; - } - - scr.autoVolume = av; - - if (level.isClientSide) - WebDisplays.PROXY.screenUpdateAutoVolumeInGui(new Vector3i(getBlockPos()), side, av); - else { - WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.autoVolume(this, side, av)); - setChanged(); - } - } + ItemStack isCopy = is.copy(); //FIXME: Duct tape fix, because the original stack will be shrinked + scr.upgrades.add(isCopy); + itemAsUpgrade.onInstall(this, side, player, isCopy); + return false; + } + + Screen scr = getScreen(side); + 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)) { + 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) { + 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))) + return false; //Upgrade already exists + + ItemStack isCopy = is.copy(); //FIXME: Duct tape fix, because the original stack will be shrinked + isCopy.setCount(1); + + scr.upgrades.add(isCopy); + if (player != null && !player.level().isClientSide) { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.upgrade(this, side, true, is)); + itemAsUpgrade.onInstall(this, side, player, isCopy); + playSoundAt(WebDisplays.INSTANCE.soundUpgradeAdd, getBlockPos(), 1.0f, 1.0f); + } + setChanged(); + return true; + } + + public boolean hasUpgrade(BlockSide side, ItemStack is) { + Screen scr = getScreen(side); + if (scr == null) + return false; + + if (!(is.getItem() instanceof IUpgrade)) + return false; + + IUpgrade itemAsUpgrade = (IUpgrade) is.getItem(); + return scr.upgrades.stream().anyMatch(otherStack -> itemAsUpgrade.isSameUpgrade(is, otherStack)); + } + + public boolean hasUpgrade(BlockSide side, DefaultUpgrade du) { + Screen scr = getScreen(side); + if (du == DefaultUpgrade.LASERMOUSE) { + return scr != null && scr.upgrades.stream().anyMatch(du::matchesLaserMouse); + } else if (du == DefaultUpgrade.REDINPUT) { + return scr != null && scr.upgrades.stream().anyMatch(du::matchesRedInput); + } else if (du == DefaultUpgrade.GPS) { + return scr != null && scr.upgrades.stream().anyMatch(du::matchesGps); + } else if (du == DefaultUpgrade.REDOUTPUT) { + return scr != null && scr.upgrades.stream().anyMatch(du::matchesRedOutput); + } else { + return false; + } + } + + public void removeUpgrade(BlockSide side, ItemStack is, @Nullable Player player) { + if (level.isClientSide) + return; + + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Tried to remove an upgrade on invalid screen on side %s", side.toString()); + return; + } + + 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; + } + + 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))) { + idxToRemove = i; + break; + } + } + + if (idxToRemove >= 0) { + dropUpgrade(scr.upgrades.get(idxToRemove), side, player); + scr.upgrades.remove(idxToRemove); + if (player != null && !player.level().isClientSide) { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.upgrade(this, side, false, is)); + playSoundAt(WebDisplays.INSTANCE.soundUpgradeDel, getBlockPos(), 1.0f, 1.0f); + } + setChanged(); + } else + Log.warning("Tried to remove non-existing upgrade %s to screen %s at %s", safeName(is), side.toString(), getBlockPos().toString()); + } + + private void dropUpgrade(ItemStack is, BlockSide side, @Nullable Player ply) { + if (!((IUpgrade) is.getItem()).onRemove(this, side, ply, is)) { //Drop upgrade item + boolean spawnDrop = true; + + 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) { + 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) { + level.addFreshEntity(new ItemEntity(level, pos.x, pos.y, pos.z, is)); + } + } + } + } + + private Screen getScreenForLaserOp(BlockSide side, Player ply) { + if (level.isClientSide) + return null; + + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Called laser operation on invalid screen on side %s", side.toString()); + return null; + } + + if ((scr.rightsFor(ply) & ScreenRights.INTERACT) == 0) + return null; //Don't output an error, it can 'legally' happen + + if (scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matchesLaserMouse)) { + Log.error("Called laser operation on side %s, but it's missing the laser sensor upgrade", side.toString()); + return null; + } + + return scr; //Okay, go for it... + } + + public void laserDownMove(BlockSide side, Player ply, Vector2i pos, boolean down, int button) { + Screen scr = getScreenForLaserOp(side, ply); + + if (scr != null) { + if (button == -1) + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.MOVE, pos)); + else if (down) + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.DOWN, pos)); + else + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.UP, pos)); + } + } + + public void laserUp(BlockSide side, Player ply, int button) { + Screen scr = getScreenForLaserOp(side, ply); + + if (scr != null) { + if (getLaserUser(scr) == ply) { + scr.laserUser = null; + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(ply, level, getBlockPos())), S2CMessageScreenUpdate.click(this, side, ClickControl.ControlType.UP, null)); + } + } + } + + public void onDestroy(@Nullable Player ply) { + for (Screen scr : screens) { + scr.upgrades.forEach(is -> dropUpgrade(is, scr.side, ply)); + scr.upgrades.clear(); + } + + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), new S2CMessageCloseGui(getBlockPos())); + } + + public void setOwner(BlockSide side, Player newOwner) { + if (level.isClientSide) { + Log.error("Called TileEntityScreen.setOwner() on client..."); + return; + } + + if (newOwner == null) { + Log.error("Called TileEntityScreen.setOwner() with null owner"); + return; + } + + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Called TileEntityScreen.setOwner() on invalid screen on side %s", side.toString()); + return; + } + + scr.owner = new NameUUIDPair(newOwner.getGameProfile()); + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.owner(this, side, scr.owner)); + checkLaserUserRights(scr); + setChanged(); + } + + public void setRotation(BlockSide side, Rotation rot) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Trying to change rotation of invalid screen on side %s", side.toString()); + return; + } + + 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) { + scr.browser.close(true); + scr.browser = null; //Will be re-created by renderer + } + } else { + scr.rotation = rot; + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.rotation(this, side, rot)); + setChanged(); + } + } + +// public void evalJS(BlockSide side, String code) { +// Screen scr = getScreen(side); +// 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) +// scr.browser.runJS(code, ""); +// } +//// else WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.js(this, side, code)); +// } + + public void setAutoVolume(BlockSide side, boolean av) { + Screen scr = getScreen(side); + if (scr == null) { + Log.error("Trying to toggle auto-volume on invalid screen (side %s)", side.toString()); + return; + } + + scr.autoVolume = av; + + if (level.isClientSide) + WebDisplays.PROXY.screenUpdateAutoVolumeInGui(new Vector3i(getBlockPos()), side, av); + else { + WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(level, getBlockPos())), S2CMessageScreenUpdate.autoVolume(this, side, av)); + setChanged(); + } + } // @Override diff --git a/src/main/java/net/montoyo/wd/init/BlockInit.java b/src/main/java/net/montoyo/wd/init/BlockInit.java index b276e6d..9ed24f9 100644 --- a/src/main/java/net/montoyo/wd/init/BlockInit.java +++ b/src/main/java/net/montoyo/wd/init/BlockInit.java @@ -1,8 +1,8 @@ package net.montoyo.wd.init; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.material.Material; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @@ -21,7 +21,7 @@ public class BlockInit { public static DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, "webdisplays"); - public static final RegistryObject blockScreen = BLOCKS.register("screen", () -> new BlockScreen(BlockBehaviour.Properties.of(Material.STONE))); + public static final RegistryObject blockScreen = BLOCKS.register("screen", () -> new BlockScreen(BlockBehaviour.Properties.copy(Blocks.STONE))); public static final RegistryObject blockKeyBoard = BlockInit.BLOCKS.register("kb_left", BlockKeyboardLeft::new); public static final RegistryObject blockKbRight = BLOCKS.register("kb_right", BlockKeyboardRight::new); diff --git a/src/main/java/net/montoyo/wd/item/ItemLaserPointer.java b/src/main/java/net/montoyo/wd/item/ItemLaserPointer.java index c4f91ce..4347730 100644 --- a/src/main/java/net/montoyo/wd/item/ItemLaserPointer.java +++ b/src/main/java/net/montoyo/wd/item/ItemLaserPointer.java @@ -14,7 +14,6 @@ import net.minecraft.world.phys.HitResult; import net.montoyo.wd.WebDisplays; import net.montoyo.wd.block.BlockScreen; import net.montoyo.wd.client.ClientProxy; -import net.montoyo.wd.client.JSQueryDispatcher; import net.montoyo.wd.config.ClientConfig; import net.montoyo.wd.controls.builtin.ClickControl; import net.montoyo.wd.core.DefaultUpgrade; @@ -79,7 +78,7 @@ public class ItemLaserPointer extends Item implements WDItem { } } - public static void deselect(Minecraft mc, JSQueryDispatcher jsDispatcher) { + public static void deselect(Minecraft mc) { deselectScreen(); } diff --git a/src/main/java/net/montoyo/wd/utilities/VideoType.java b/src/main/java/net/montoyo/wd/utilities/VideoType.java index f05d4ce..aaaa719 100644 --- a/src/main/java/net/montoyo/wd/utilities/VideoType.java +++ b/src/main/java/net/montoyo/wd/utilities/VideoType.java @@ -4,8 +4,6 @@ package net.montoyo.wd.utilities; -import net.montoyo.wd.client.JSQueryDispatcher; - import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.net.MalformedURLException; @@ -46,9 +44,9 @@ public enum VideoType { volumeCap = volume.prefix.length() + 5 + volume.suffix.length(); } - public static void registerQueries(JSQueryDispatcher jsQueryDispatcher) { - // TODO: register GetTime query - } +// public static void registerQueries(JSQueryDispatcher jsQueryDispatcher) { +// // TODO: register GetTime query +// } protected static class Function { String prefix, suffix;