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 0000000..0518005 Binary files /dev/null and b/libs/mcef-2.x.jar differ diff --git a/src/main/java/net/montoyo/wd/block/BlockKeyboardRight.java b/src/main/java/net/montoyo/wd/block/BlockKeyboardRight.java index c38b17b..b27f8b5 100644 --- a/src/main/java/net/montoyo/wd/block/BlockKeyboardRight.java +++ b/src/main/java/net/montoyo/wd/block/BlockKeyboardRight.java @@ -17,7 +17,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.material.Material; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; @@ -41,7 +40,7 @@ public class BlockKeyboardRight extends Block implements IPeripheral { public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; public BlockKeyboardRight() { - super(Properties.of(Material.STONE) + super(Properties.copy(Blocks.STONE) .strength(1.5f, 10.f)); } diff --git a/src/main/java/net/montoyo/wd/block/BlockPeripheral.java b/src/main/java/net/montoyo/wd/block/BlockPeripheral.java index 4acf076..bb5b638 100644 --- a/src/main/java/net/montoyo/wd/block/BlockPeripheral.java +++ b/src/main/java/net/montoyo/wd/block/BlockPeripheral.java @@ -15,19 +15,18 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.network.PacketDistributor; -import net.montoyo.mcef.utilities.Log; import net.montoyo.wd.core.DefaultPeripheral; import net.montoyo.wd.entity.TileEntityInterfaceBase; import net.montoyo.wd.entity.TileEntityPeripheralBase; @@ -35,13 +34,14 @@ import net.montoyo.wd.entity.TileEntityServer; import net.montoyo.wd.item.ItemLinker; import net.montoyo.wd.net.WDNetworkRegistry; import net.montoyo.wd.net.client_bound.S2CMessageCloseGui; +import net.montoyo.wd.utilities.Log; import org.jetbrains.annotations.Nullable; public class BlockPeripheral extends WDBlockContainer { DefaultPeripheral type; public BlockPeripheral(DefaultPeripheral type) { - super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f)); + super(BlockBehaviour.Properties.copy(Blocks.STONE).strength(1.5f, 10.f)); this.type = type; } diff --git a/src/main/java/net/montoyo/wd/client/ClientProxy.java b/src/main/java/net/montoyo/wd/client/ClientProxy.java index b7e414a..c5a0500 100644 --- a/src/main/java/net/montoyo/wd/client/ClientProxy.java +++ b/src/main/java/net/montoyo/wd/client/ClientProxy.java @@ -740,11 +740,11 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer if (LaserPointerRenderer.isOn()) { ItemLaserPointer.tick(mc); } else { - ItemLaserPointer.deselect(mc, jsDispatcher); + ItemLaserPointer.deselect(mc); } - //Handle JS queries - jsDispatcher.handleQueries(); +// //Handle JS queries +// jsDispatcher.handleQueries(); //Miniserv if (msClientStarted && mc.player == null) { diff --git a/src/main/java/net/montoyo/wd/client/JSQueryDispatcher.java b/src/main/java/net/montoyo/wd/client/JSQueryDispatcher.java index 7bd5ee0..a50ab70 100644 --- a/src/main/java/net/montoyo/wd/client/JSQueryDispatcher.java +++ b/src/main/java/net/montoyo/wd/client/JSQueryDispatcher.java @@ -1,372 +1,370 @@ -/* - * 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.mcef.api.IBrowser; -import net.montoyo.mcef.api.IJSQueryCallback; -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() + "}")); - } - -} +///* +// * 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;