large reworks of network code, various fixes

This commit is contained in:
GiantLuigi4 2023-03-14 13:00:34 -04:00
parent 3c141d9e1b
commit bc16cf9769
37 changed files with 1190 additions and 677 deletions

View File

@ -80,7 +80,7 @@ dependencies {
implementation fg.deobf("curse.maven:SU-370704:4410614") implementation fg.deobf("curse.maven:SU-370704:4410614")
implementation fg.deobf("curse.maven:spark-361579:4381167") implementation fg.deobf("curse.maven:spark-361579:4381167")
implementation fg.deobf("curse.maven:vivecraft-667903:4409427") compileOnly fg.deobf("curse.maven:vivecraft-667903:4409427")
} }
sourceSets { sourceSets {

View File

@ -41,6 +41,7 @@ import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.montoyo.wd.config.ModConfig; import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.controls.ScreenControlRegistry;
import net.montoyo.wd.core.*; import net.montoyo.wd.core.*;
import net.montoyo.wd.init.BlockInit; import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.init.ItemInit; import net.montoyo.wd.init.ItemInit;
@ -185,6 +186,10 @@ public class WebDisplays {
t.printStackTrace(); t.printStackTrace();
} }
} */ } */
if (!FMLEnvironment.production) {
ScreenControlRegistry.init();
}
} }
@SubscribeEvent @SubscribeEvent

View File

@ -194,13 +194,18 @@ public class BlockScreen extends BaseEntityBlock {
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
} else { } else {
if ((scr.rightsFor(player) & ScreenRights.CLICK) == 0) { if ((scr.rightsFor(player) & ScreenRights.INTERACT) == 0) {
Util.toast(player, "restrictions"); Util.toast(player, "restrictions");
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
Vector2i tmp = new Vector2i(); Vector2i tmp = new Vector2i();
if (hit2pixels(side, hit.getBlockPos(), pos, scr, (float) hit.getLocation().x, (float) hit.getLocation().y, (float) hit.getLocation().z, tmp))
float hitX = ((float) hit.getLocation().x) - (float) te.getBlockPos().getX();
float hitY = ((float) hit.getLocation().y) - (float) te.getBlockPos().getY();
float hitZ = ((float) hit.getLocation().z) - (float) te.getBlockPos().getZ();
if (hit2pixels(side, hit.getBlockPos(), new Vector3i(hit.getBlockPos()), scr, hitX, hitY, hitZ, tmp))
te.click(side, tmp); te.click(side, tmp);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
@ -259,67 +264,64 @@ public class BlockScreen extends BaseEntityBlock {
} }
} }
public static boolean hit2pixels (BlockSide side, BlockPos bpos, Vector3i pos, TileEntityScreen.Screen scr, public static boolean hit2pixels(BlockSide side, BlockPos bpos, Vector3i pos, TileEntityScreen.Screen scr, float hitX, float hitY, float hitZ, Vector2i dst) {
float hitX, float hitY, float hitZ, Vector2i dst){ if(side.right.x < 0)
if (side.right.x < 0) hitX -= 1.f;
hitX -= 1.f;
if (side.right.z < 0 || side == BlockSide.TOP || side == BlockSide.BOTTOM) if(side.right.z < 0 || side == BlockSide.TOP || side == BlockSide.BOTTOM)
hitZ -= 1.f; hitZ -= 1.f;
Vector3f rel = new Vector3f(hitX, hitY, hitZ); Vector3f rel = new Vector3f(bpos.getX(), bpos.getY(), bpos.getZ());
rel.sub(pos.toBlock().getX(), pos.toBlock().getY(), pos.toBlock().getZ()); rel.sub((float) pos.x, (float) pos.y, (float) pos.z);
rel.add(hitX, hitY, hitZ);
float cx = Math.abs(rel.dot(side.right.toFloat()) - 2.f / 16.f); float cx = rel.dot(side.right.toFloat()) - 2.f / 16.f;
float cy = Math.abs(rel.dot(side.up.toFloat()) - 2.f / 16.f); float cy = rel.dot(side.up.toFloat()) - 2.f / 16.f;
float sw = ((float) scr.size.x) - 4.f / 16.f; float sw = ((float) scr.size.x) - 4.f / 16.f;
float sh = ((float) scr.size.y) - 4.f / 16.f; float sh = ((float) scr.size.y) - 4.f / 16.f;
cx /= sw; cx /= sw;
cy /= sh; cy /= sh;
cx = cx - 0.05f; if(cx >= 0.f && cx <= 1.0 && cy >= 0.f && cy <= 1.f) {
cy = cy - 0.05f; if(side != BlockSide.BOTTOM)
cy = 1.f - cy;
if (cx >= 0 && cx <= 1 && cy >= 0 && cy <= 1) { switch(scr.rotation) {
if (side != BlockSide.BOTTOM) case ROT_90:
cy = 1.f - cy; cy = 1.0f - cy;
break;
switch (scr.rotation) { case ROT_180:
case ROT_90: cx = 1.0f - cx;
cy = 1.0f - cy; cy = 1.0f - cy;
break; break;
case ROT_180: case ROT_270:
cx = 1.0f - cx; cx = 1.0f - cx;
cy = 1.0f - cy; break;
break;
case ROT_270: default:
cx = 1.0f - cx; break;
break;
default:
break;
}
cx *= (float) scr.resolution.x;
cy *= (float) scr.resolution.y;
if (scr.rotation.isVertical) {
dst.x = (int) cy;
dst.y = (int) cx;
} else {
dst.x = (int) cx;
dst.y = (int) cy;
}
return true;
} }
return false; cx *= (float) scr.resolution.x;
cy *= (float) scr.resolution.y;
if(scr.rotation.isVertical) {
dst.x = (int) cy;
dst.y = (int) cx;
} else {
dst.x = (int) cx;
dst.y = (int) cy;
}
return true;
} }
return false;
}
@org.jetbrains.annotations.Nullable @org.jetbrains.annotations.Nullable
@Override @Override
public BlockEntity newBlockEntity (BlockPos pos, BlockState state){ public BlockEntity newBlockEntity (BlockPos pos, BlockState state){

View File

@ -631,7 +631,7 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer
float hitZ = ((float) result.getLocation().z) - (float) bpos.getZ(); float hitZ = ((float) result.getLocation().z) - (float) bpos.getZ();
Vector2i tmp = new Vector2i(); Vector2i tmp = new Vector2i();
if(BlockScreen.hit2pixels(side, bpos, pos, scr, hitX, hitY, hitZ, tmp)) { if(BlockScreen.hit2pixels(side, bpos, new Vector3i(result.getBlockPos()), scr, hitX, hitY, hitZ, tmp)) {
laserClick(te, side, scr, tmp); laserClick(te, side, scr, tmp);
} }
} }
@ -694,13 +694,13 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer
if(t - lastPointPacket >= 100) { if(t - lastPointPacket >= 100) {
lastPointPacket = t; lastPointPacket = t;
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.vec2(tes, side, C2SMessageScreenCtrl.CTRL_LASER_MOVE, hit)); WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserMove(tes, side, hit));
} }
} else { } else {
deselectScreen(); deselectScreen();
pointedScreen = tes; pointedScreen = tes;
pointedScreenSide = side; pointedScreenSide = side;
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.vec2(tes, side, C2SMessageScreenCtrl.CTRL_LASER_DOWN, hit)); WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserDown(tes, side, hit));
} }
} }
@ -802,6 +802,8 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer
@Override @Override
public BlockGetter getWorld(NetworkEvent.Context context) { public BlockGetter getWorld(NetworkEvent.Context context) {
return Minecraft.getInstance().level; BlockGetter senderLevel = super.getWorld(context);
if (senderLevel == null) return Minecraft.getInstance().level;
return senderLevel;
} }
} }

View File

@ -133,17 +133,17 @@ public class GuiScreenConfig extends WDScreen {
loadFrom(new ResourceLocation("webdisplays", "gui/screencfg.json")); loadFrom(new ResourceLocation("webdisplays", "gui/screencfg.json"));
friendBoxes = new CheckBox[] { boxFResolution, boxFUpgrades, boxFOthers, boxFFriends, boxFClick, boxFSetUrl }; friendBoxes = new CheckBox[] { boxFResolution, boxFUpgrades, boxFOthers, boxFFriends, boxFClick, boxFSetUrl };
boxFResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION); boxFResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxFUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES); boxFUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxFOthers.setUserdata(ScreenRights.MANAGE_OTHER_RIGHTS); boxFOthers.setUserdata(ScreenRights.MANAGE_OTHER_RIGHTS);
boxFFriends.setUserdata(ScreenRights.MANAGE_FRIEND_LIST); boxFFriends.setUserdata(ScreenRights.MANAGE_FRIEND_LIST);
boxFClick.setUserdata(ScreenRights.CLICK); boxFClick.setUserdata(ScreenRights.INTERACT);
boxFSetUrl.setUserdata(ScreenRights.CHANGE_URL); boxFSetUrl.setUserdata(ScreenRights.CHANGE_URL);
otherBoxes = new CheckBox[] { boxOResolution, boxOUpgrades, boxOClick, boxOSetUrl }; otherBoxes = new CheckBox[] { boxOResolution, boxOUpgrades, boxOClick, boxOSetUrl };
boxOResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION); boxOResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxOUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES); boxOUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxOClick.setUserdata(ScreenRights.CLICK); boxOClick.setUserdata(ScreenRights.INTERACT);
boxOSetUrl.setUserdata(ScreenRights.CHANGE_URL); boxOSetUrl.setUserdata(ScreenRights.CHANGE_URL);
TileEntityScreen.Screen scr = tes.getScreen(side); TileEntityScreen.Screen scr = tes.getScreen(side);
@ -201,7 +201,7 @@ public class GuiScreenConfig extends WDScreen {
throw new NumberFormatException(); //I'm lazy throw new NumberFormatException(); //I'm lazy
if(x != scr.resolution.x || y != scr.resolution.y) if(x != scr.resolution.x || y != scr.resolution.y)
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.vec2(tes, side, C2SMessageScreenCtrl.CTRL_SET_RESOLUTION, new Vector2i(x, y))); WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.resolution(tes, side, new Vector2i(x, y)));
} catch(NumberFormatException ex) { } catch(NumberFormatException ex) {
//Roll back //Roll back
tfResX.setText("" + scr.resolution.x); tfResX.setText("" + scr.resolution.x);
@ -455,7 +455,7 @@ public class GuiScreenConfig extends WDScreen {
flag = (myRights & ScreenRights.MANAGE_OTHER_RIGHTS) == 0; flag = (myRights & ScreenRights.MANAGE_OTHER_RIGHTS) == 0;
grpOthers.setDisabled(flag); grpOthers.setDisabled(flag);
flag = (myRights & ScreenRights.CHANGE_RESOLUTION) == 0; flag = (myRights & ScreenRights.MODIFY_SCREEN) == 0;
tfResX.setDisabled(flag); tfResX.setDisabled(flag);
tfResY.setDisabled(flag); tfResY.setDisabled(flag);
btnChangeRot.setDisabled(flag); btnChangeRot.setDisabled(flag);

View File

@ -18,116 +18,153 @@ import org.jetbrains.annotations.NotNull;
import static com.mojang.math.Vector3f.*; import static com.mojang.math.Vector3f.*;
public class ScreenRenderer implements BlockEntityRenderer<TileEntityScreen> { public class ScreenRenderer implements BlockEntityRenderer<TileEntityScreen> {
public ScreenRenderer() {} public ScreenRenderer() {
}
public static class ScreenRendererProvider implements BlockEntityRendererProvider<TileEntityScreen> { public static class ScreenRendererProvider implements BlockEntityRendererProvider<TileEntityScreen> {
@Override @Override
public @NotNull BlockEntityRenderer<TileEntityScreen> create(@NotNull Context arg) { public @NotNull BlockEntityRenderer<TileEntityScreen> create(@NotNull Context arg) {
return new ScreenRenderer(); return new ScreenRenderer();
} }
} }
private final Vector3f mid = new Vector3f(); private final Vector3f mid = new Vector3f();
private final Vector3i tmpi = new Vector3i(); private final Vector3i tmpi = new Vector3i();
private final Vector3f tmpf = new Vector3f(); private final Vector3f tmpf = new Vector3f();
@Override @Override
public void render(TileEntityScreen te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) { public void render(TileEntityScreen te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
if(!te.isLoaded()) if (!te.isLoaded())
return; return;
//Disable lighting //Disable lighting
RenderSystem.enableTexture(); RenderSystem.enableTexture();
// RenderSystem.disableCull(); // RenderSystem.disableCull();
RenderSystem.disableBlend(); RenderSystem.disableBlend();
for(int i = 0; i < te.screenCount(); i++) { for (int i = 0; i < te.screenCount(); i++) {
TileEntityScreen.Screen scr = te.getScreen(i); TileEntityScreen.Screen scr = te.getScreen(i);
if(scr.browser == null) { if (scr.browser == null) {
scr.createBrowser(true); scr.createBrowser(true);
} }
// TODO: manually backface cull the screens // TODO: manually backface cull the screens
tmpi.set(scr.side.right); tmpi.set(scr.side.right);
tmpi.mul(scr.size.x); tmpi.mul(scr.size.x);
tmpi.addMul(scr.side.up, scr.size.y); tmpi.addMul(scr.side.up, scr.size.y);
tmpf.set(tmpi); tmpf.set(tmpi);
mid.set(0.5, 0.5, 0.5); mid.set(0.5, 0.5, 0.5);
mid.addMul(tmpf, 0.5f); mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.left); tmpf.set(scr.side.left);
mid.addMul(tmpf, 0.5f); mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.down); tmpf.set(scr.side.down);
mid.addMul(tmpf, 0.5f); mid.addMul(tmpf, 0.5f);
poseStack.pushPose(); poseStack.pushPose();
poseStack.translate(mid.x, mid.y, mid.z); poseStack.translate(mid.x, mid.y, mid.z);
switch(scr.side) { switch (scr.side) {
case BOTTOM: case BOTTOM:
poseStack.mulPose(XP.rotation(90.f + 49.8f)); poseStack.mulPose(XP.rotation(90.f + 49.8f));
break; break;
case TOP: case TOP:
poseStack.mulPose(XN.rotation(90.f + 49.8f)); poseStack.mulPose(XN.rotation(90.f + 49.8f));
break; break;
case NORTH: case NORTH:
poseStack.mulPose(YN.rotationDegrees(180.f)); poseStack.mulPose(YN.rotationDegrees(180.f));
break; break;
case SOUTH: case SOUTH:
break; break;
case WEST: case WEST:
poseStack.mulPose(YN.rotationDegrees(90.f)); poseStack.mulPose(YN.rotationDegrees(90.f));
break; break;
case EAST: case EAST:
poseStack.mulPose(YP.rotationDegrees(90.f)); poseStack.mulPose(YP.rotationDegrees(90.f));
break; break;
} }
if(scr.doTurnOnAnim) { if (scr.doTurnOnAnim) {
long lt = System.currentTimeMillis() - scr.turnOnTime; long lt = System.currentTimeMillis() - scr.turnOnTime;
float ft = ((float) lt) / 100.0f; float ft = ((float) lt) / 100.0f;
if(ft >= 1.0f) { if (ft >= 1.0f) {
ft = 1.0f; ft = 1.0f;
scr.doTurnOnAnim = false; scr.doTurnOnAnim = false;
} }
poseStack.scale(ft, ft, 1.0f); poseStack.scale(ft, ft, 1.0f);
} }
if(!scr.rotation.isNull) if (!scr.rotation.isNull)
poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle)); poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle));
float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f; float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f;
float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f; float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f;
if(scr.rotation.isVertical) { if (scr.rotation.isVertical) {
float tmp = sw; float tmp = sw;
sw = sh; sw = sh;
sh = tmp; sh = tmp;
} }
Tesselator tesselator = Tesselator.getInstance(); Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder(); BufferBuilder builder = tesselator.getBuilder();
//TODO: don't use tesselator //TODO: don't use tesselator
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader); RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem._setShaderTexture(0, scr.browser.getTextureID()); RenderSystem._setShaderTexture(0, scr.browser.getTextureID());
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); 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(); builder.vertex(poseStack.last().pose(), -sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex(); builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex(); builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(),-sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex(); builder.vertex(poseStack.last().pose(), -sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
tesselator.end();//Minecraft does shit with mah texture otherwise... tesselator.end();//Minecraft does shit with mah texture otherwise...
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
poseStack.popPose();
} // TODO: it'd be neat to draw a mouse cursor on the screen
// // debug hit2pixels
// HitResult result = Minecraft.getInstance().hitResult;
// VertexConsumer consumer = bufferSource.getBuffer(RenderType.lines());
// poseStack.translate(-sw, -sh, 0);
// if (result instanceof BlockHitResult hit) {
// BlockPos bpos = hit.getBlockPos();
//
// Vector3i pos = new Vector3i(hit.getBlockPos());
// float hitX = ((float) result.getLocation().x) - (float) te.getBlockPos().getX();
// float hitY = ((float) result.getLocation().y) - (float) te.getBlockPos().getY();
// float hitZ = ((float) result.getLocation().z) - (float) te.getBlockPos().getZ();
// Vector2i tmp = new Vector2i();
//
// if (BlockScreen.hit2pixels(scr.side, bpos, pos, scr, hitX, hitY, hitZ, tmp)) {
// float x = tmp.x / (float) scr.resolution.x * scr.size.x;
// float y = tmp.y / (float) scr.resolution.y * scr.size.y;
// y = scr.size.y - y;
//
// x /= scr.size.x;
// y /= scr.size.y;
// x *= sw * 2;
// y *= sh * 2;
//
// LevelRenderer.renderLineBox(
// poseStack,
// consumer, new AABB(
// x - 0.01, y - 0.01, 0.5 - 0.01,
// x + 0.01, y + 0.01, 0.5 + 0.01
// ),
// 1f, 0, 0, 1f
// );
// }
// }
poseStack.popPose();
}
// //Bounding box debugging // //Bounding box debugging
@ -139,7 +176,7 @@ public class ScreenRenderer implements BlockEntityRenderer<TileEntityScreen> {
// ); // );
// poseStack.popPose(); // poseStack.popPose();
//Re-enable lighting //Re-enable lighting
// RenderSystem.enableCull(); // RenderSystem.enableCull();
} }
} }

View File

@ -0,0 +1,38 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import java.util.Objects;
import java.util.function.Function;
public abstract class ScreenControl {
private final ResourceLocation id;
public ScreenControl(ResourceLocation id) {
this.id = id;
}
public abstract void write(FriendlyByteBuf buf);
public abstract void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException;
@OnlyIn(Dist.CLIENT)
public abstract void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx);
public void checkPerms(int perms, Function<Integer, Boolean> checker, ServerPlayer player) throws MissingPermissionException {
if (!checker.apply(perms)) {
throw new MissingPermissionException(perms, Objects.requireNonNull(player));
}
}
public final ResourceLocation getId() {
return id;
}
}

View File

@ -0,0 +1,73 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.builtin.*;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Log;
import java.lang.reflect.Method;
import java.util.HashMap;
// TODO: enable deferred registry of these
public class ScreenControlRegistry {
private static final HashMap<ResourceLocation, ScreenControlType<?>> CONTROL_TYPES = new HashMap<>();
public static void register(ResourceLocation name, ScreenControlType<?> type) {
if (CONTROL_TYPES.containsKey(name)) {
Log.warning("ScreenControlRegistry#CONTROL_TYPES already contains an entry with name " + name);
throw new IllegalArgumentException("Cannot have two entries with the same name.");
}
CONTROL_TYPES.put(name, type);
// lil thing for sanity
// avoids the pain the dist cleaner causes, hopefully
if (!FMLEnvironment.production) {
if (FMLEnvironment.dist.isClient()) {
boolean shouldThrow = false;
try {
Method m = type.clazz.getMethod("handleClient", BlockPos.class, BlockSide.class, TileEntityScreen.class, NetworkEvent.Context.class);
OnlyIn onlyIn = m.getAnnotation(OnlyIn.class);
if (onlyIn == null) shouldThrow = true;
Dist d = onlyIn.value(); // idc if this throws, lol
if (d != Dist.CLIENT) shouldThrow = true;
} catch (Throwable ignored) {
}
if (shouldThrow) {
Log.warning("handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz);
throw new IllegalStateException(
"handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz
);
}
}
}
}
// if needed, the old code
// https://github.com/Mysticpasta1/webdisplays/blob/ff55cbf1b27773c15f44f17ad3364da3a16b6ed9/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java
static {
register(SetURLControl.id, new ScreenControlType<>(SetURLControl.class, SetURLControl::new));
register(KeyTypedControl.id, new ScreenControlType<>(KeyTypedControl.class, KeyTypedControl::new));
register(AutoVolumeControl.id, new ScreenControlType<>(AutoVolumeControl.class, AutoVolumeControl::new));
register(JSRequestControl.id, new ScreenControlType<>(JSRequestControl.class, JSRequestControl::new));
register(LaserControl.id, new ScreenControlType<>(LaserControl.class, LaserControl::new));
register(ScreenModifyControl.id, new ScreenControlType<>(ScreenModifyControl.class, ScreenModifyControl::new));
register(ModifyFriendListControl.id, new ScreenControlType<>(ModifyFriendListControl.class, ModifyFriendListControl::new));
register(ManageRightsAndUpdgradesControl.id, new ScreenControlType<>(ManageRightsAndUpdgradesControl.class, ManageRightsAndUpdgradesControl::new));
}
public static ScreenControl parse(FriendlyByteBuf buf) {
return CONTROL_TYPES.get(new ResourceLocation(buf.readUtf()))
.deserializer.apply(buf);
}
public static void init() {
/* NO-OP: allows static init to run during mod init in dev env */
}
}

View File

@ -0,0 +1,15 @@
package net.montoyo.wd.controls;
import net.minecraft.network.FriendlyByteBuf;
import java.util.function.Function;
public class ScreenControlType<T extends ScreenControl> {
Class<T> clazz;
Function<FriendlyByteBuf, ScreenControl> deserializer;
public ScreenControlType(Class<T> clazz, Function<FriendlyByteBuf, ScreenControl> deserializer) {
this.clazz = clazz;
this.deserializer = deserializer;
}
}

View File

@ -0,0 +1,49 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import java.util.function.Function;
public class AutoVolumeControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:auto_volume");
boolean autoVol;
public AutoVolumeControl(boolean autoVol) {
super(id);
this.autoVol = autoVol;
}
public AutoVolumeControl(FriendlyByteBuf buf) {
super(id);
autoVol = buf.readBoolean();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(autoVol);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// I feel like there's probably a better permission category
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
tes.setAutoVolume(side, autoVol);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
tes.setAutoVolume(side, autoVol);
}
}

View File

@ -0,0 +1,63 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Log;
import java.util.function.Function;
public class JSRequestControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:js_req");
int reqId;
JSServerRequest reqType;
Object[] data;
public JSRequestControl(int reqId, JSServerRequest reqType, Object[] data) {
super(id);
this.reqId = reqId;
this.reqType = reqType;
this.data = data;
}
public JSRequestControl(FriendlyByteBuf buf) {
super(id);
reqId = buf.readInt();
reqType = JSServerRequest.fromID(buf.readByte());
if (reqType != null)
data = reqType.deserialize(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeInt(reqId);
buf.writeByte(reqType.ordinal());
if (!reqType.serialize(buf, data))
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + reqType);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
if (reqType == null || data == null) Log.warning("Caught invalid JS request from player %s (UUID %s)", player.getName(), player.getGameProfile().getId().toString());
else tes.handleJSRequest(player, side, reqId, reqType, data);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,52 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import java.util.function.Function;
public class KeyTypedControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:type");
String text;
BlockPos soundPos;
public KeyTypedControl(String text, BlockPos soundPos) {
super(id);
this.text = text;
this.soundPos = soundPos;
}
public KeyTypedControl(FriendlyByteBuf buf) {
super(id);
text = buf.readUtf();
soundPos = buf.readBlockPos();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(text);
buf.writeBlockPos(soundPos);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
tes.type(side, text, soundPos);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
tes.type(side, text, soundPos);
}
}

View File

@ -0,0 +1,64 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector2i;
import java.util.function.Function;
public class LaserControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:laser");
public static enum ControlType {
MOVE, DOWN, UP
}
ControlType type;
Vector2i coord;
public LaserControl(ControlType type, Vector2i coord) {
super(id);
this.type = type;
this.coord = coord;
}
public LaserControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (!type.equals(ControlType.UP))
coord = new Vector2i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (coord != null) coord.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// feel like this makes sense, but I wanna get opinions first
// checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
ServerPlayer sender = ctx.getSender();
switch (type) {
case UP -> tes.laserUp(side, sender);
case DOWN -> tes.laserDownMove(side, sender, coord, true);
case MOVE -> tes.laserDownMove(side, sender, coord, false);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,97 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import java.util.function.Function;
/**
* TODO: I'm considering merging this with {@link ModifyFriendListControl} to make ManageScreenControl
*/
@Deprecated
public class ManageRightsAndUpdgradesControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_rights_upgrades");
public static enum ControlType {
RIGHTS, UPGRADES
}
ControlType type;
ItemStack toRemove;
private int friendRights;
private int otherRights;
public ManageRightsAndUpdgradesControl(ItemStack toRemove) {
super(id);
type = ControlType.UPGRADES;
this.toRemove = toRemove;
}
public ManageRightsAndUpdgradesControl(int friendRights, int otherRights) {
super(id);
this.friendRights = friendRights;
this.otherRights = otherRights;
}
public ManageRightsAndUpdgradesControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
switch (type) {
case UPGRADES -> toRemove = buf.readItem();
case RIGHTS -> {
friendRights = buf.readInt();
otherRights = buf.readInt();
}
}
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
switch (type) {
case UPGRADES -> buf.writeItem(toRemove);
case RIGHTS -> {
buf.writeInt(friendRights);
buf.writeInt(otherRights);
}
}
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
switch (type) {
case UPGRADES -> {
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
tes.removeUpgrade(side, toRemove, player);
}
case RIGHTS -> {
TileEntityScreen.Screen scr = tes.getScreen(side);
int fr = scr.owner.uuid.equals(player.getGameProfile().getId()) ? friendRights : scr.friendRights;
int or = (scr.rightsFor(player) & ScreenRights.MANAGE_OTHER_RIGHTS) == 0 ? scr.otherRights : otherRights;
if(scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,56 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.NameUUIDPair;
import java.util.function.Function;
public class ModifyFriendListControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_friend_list");
boolean adding;
NameUUIDPair friend;
public ModifyFriendListControl(NameUUIDPair pair, boolean adding) {
super(id);
this.adding = adding;
this.friend = pair;
}
public ModifyFriendListControl(FriendlyByteBuf buf) {
super(id);
adding = buf.readBoolean();
friend = new NameUUIDPair(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(adding);
friend.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
checkPerms(ScreenRights.MANAGE_FRIEND_LIST, permissionChecker, ctx.getSender());
if (adding) tes.addFriend(player, side, friend);
else tes.removeFriend(player, side, friend);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,71 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Rotation;
import net.montoyo.wd.utilities.Vector2i;
import java.util.function.Function;
public class ScreenModifyControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_screen");
public static enum ControlType {
RESOLUTION, ROTATION
}
ControlType type;
Vector2i res;
Rotation rotation;
public ScreenModifyControl(Vector2i res) {
super(id);
this.type = ControlType.RESOLUTION;
this.res = res;
}
public ScreenModifyControl(Rotation rotation) {
super(id);
this.type = ControlType.ROTATION;
this.rotation = rotation;
}
public ScreenModifyControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (type.equals(ControlType.RESOLUTION))
res = new Vector2i(buf);
else rotation = Rotation.values()[buf.readByte()];
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (res != null) res.writeTo(buf);
else if (rotation != null) buf.writeByte(rotation.ordinal());
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.MODIFY_SCREEN, permissionChecker, ctx.getSender());
switch (type) {
case RESOLUTION -> tes.setResolution(side, res);
case ROTATION -> tes.setRotation(side, rotation);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,63 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3i;
import java.util.function.Function;
public class SetURLControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:set_url");
String url;
Vector3i remoteLocation;
public SetURLControl(String url, Vector3i remoteLocation) {
super(id);
this.url = url;
this.remoteLocation = remoteLocation;
}
public SetURLControl(FriendlyByteBuf buf) {
super(id);
url = buf.readUtf();
if (buf.readBoolean()) remoteLocation = new Vector3i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(url);
buf.writeBoolean(remoteLocation != null);
if (remoteLocation != null) remoteLocation.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// TODO: deal with remote
checkPerms(ScreenRights.CHANGE_URL, permissionChecker, ctx.getSender());
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, TileEntityScreen tes, NetworkEvent.Context ctx) {
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
}

View File

@ -7,14 +7,19 @@ package net.montoyo.wd.core;
public abstract class ScreenRights { public abstract class ScreenRights {
public static final int CHANGE_URL = 1; //Change URL AND run JavaScript public static final int CHANGE_URL = 1; //Change URL AND run JavaScript
/** use {@link ScreenRights#INTERACT instead} */
@Deprecated(forRemoval = true)
public static final int CLICK = 2; //Click AND type public static final int CLICK = 2; //Click AND type
public static final int INTERACT = 2; //Click AND type
public static final int MANAGE_FRIEND_LIST = 4; public static final int MANAGE_FRIEND_LIST = 4;
public static final int MANAGE_OTHER_RIGHTS = 8; public static final int MANAGE_OTHER_RIGHTS = 8;
public static final int MANAGE_UPGRADES = 16; //Manage upgrades AND peripherals AND autoVolume public static final int MANAGE_UPGRADES = 16; //Manage upgrades AND peripherals AND autoVolume
@Deprecated(forRemoval = true)
public static final int CHANGE_RESOLUTION = 32; //Change resolution AND rotation public static final int CHANGE_RESOLUTION = 32; //Change resolution AND rotation
public static final int MODIFY_SCREEN = 32; //Change resolution AND rotation
public static final int NONE = 0; public static final int NONE = 0;
public static final int ALL = 0xFF; public static final int ALL = 0xFF;
public static final int DEFAULTS = CHANGE_URL | CLICK | MANAGE_UPGRADES | CHANGE_RESOLUTION; public static final int DEFAULTS = CHANGE_URL | INTERACT | MANAGE_UPGRADES | MODIFY_SCREEN;
} }

View File

@ -100,7 +100,7 @@ public class ScreenConfigData extends GuiData {
onlyUpdate = buf.readBoolean(); onlyUpdate = buf.readBoolean();
pos = BufferUtils.readVec3i(buf); pos = BufferUtils.readVec3i(buf);
side = (BlockSide) BufferUtils.readEnum(buf, (v) -> BlockSide.values()[v], (byte) 1); side = (BlockSide) BufferUtils.readEnum(buf, (v) -> BlockSide.values()[v], (byte) 1);
friends = BufferUtils.readArray(buf, () -> new NameUUIDPair(buf)); friends = BufferUtils.readArray(buf, new NameUUIDPair[0], () -> new NameUUIDPair(buf));
friendRights = buf.readInt(); friendRights = buf.readInt();
otherRights = buf.readInt(); otherRights = buf.readInt();
} }

View File

@ -89,7 +89,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
switch(what) { switch(what) {
case "click": case "click":
case "type": case "type":
right = ScreenRights.CLICK; right = ScreenRights.INTERACT;
break; break;
case "seturl": case "seturl":
@ -101,7 +101,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
case "setresolution": case "setresolution":
case "setrotation": case "setrotation":
right = ScreenRights.CHANGE_RESOLUTION; right = ScreenRights.MODIFY_SCREEN;
break; break;
default: default:
@ -213,7 +213,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
else { else {
TileEntityScreen.Screen scrscr = scr.getScreen(screenSide); TileEntityScreen.Screen scrscr = scr.getScreen(screenSide);
if((scrscr.rightsFor(owner.uuid) & ScreenRights.CLICK) == 0) if((scrscr.rightsFor(owner.uuid) & ScreenRights.INTERACT) == 0)
return err("restrictions"); return err("restrictions");
else { else {
switch(scrscr.rotation) { switch(scrscr.rotation) {
@ -249,7 +249,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
if(owner == null || scr == null) if(owner == null || scr == null)
return err("notlinked"); return err("notlinked");
else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.CLICK) == 0) else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.INTERACT) == 0)
return err("restrictions"); return err("restrictions");
else { else {
scr.type(screenSide, what, null); scr.type(screenSide, what, null);
@ -350,7 +350,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
if(owner == null || scr == null) if(owner == null || scr == null)
return err("notlinked"); return err("notlinked");
else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.CHANGE_RESOLUTION) == 0) else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.MODIFY_SCREEN) == 0)
return err("restrictions"); return err("restrictions");
else { else {
scr.setResolution(screenSide, new Vector2i(rx, ry)); scr.setResolution(screenSide, new Vector2i(rx, ry));
@ -373,7 +373,7 @@ public abstract class TileEntityInterfaceBase extends TileEntityPeripheralBase {
if(owner == null || scr == null) if(owner == null || scr == null)
return err("notlinked"); return err("notlinked");
else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.CHANGE_RESOLUTION) == 0) else if((scr.getScreen(screenSide).rightsFor(owner.uuid) & ScreenRights.MODIFY_SCREEN) == 0)
return err("restrictions"); return err("restrictions");
else { else {
scr.setRotation(screenSide, Rotation.values()[rot]); scr.setRotation(screenSide, Rotation.values()[rot]);

View File

@ -53,7 +53,7 @@ public class TileEntityKeyboard extends TileEntityPeripheralBase {
} }
TileEntityScreen.Screen scr = tes.getScreen(screenSide); TileEntityScreen.Screen scr = tes.getScreen(screenSide);
if((scr.rightsFor(player) & ScreenRights.CLICK) == 0) { if((scr.rightsFor(player) & ScreenRights.INTERACT) == 0) {
Util.toast(player, "restrictions"); Util.toast(player, "restrictions");
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
@ -71,9 +71,9 @@ public class TileEntityKeyboard extends TileEntityPeripheralBase {
boolean ok; boolean ok;
if(ent instanceof Player) if(ent instanceof Player)
ok = (scr.rightsFor((Player) ent) & ScreenRights.CLICK) != 0; ok = (scr.rightsFor((Player) ent) & ScreenRights.INTERACT) != 0;
else else
ok = (scr.otherRights & ScreenRights.CLICK) != 0; ok = (scr.otherRights & ScreenRights.INTERACT) != 0;
if(ok) { if(ok) {
char rnd = RANDOM_CHARS.charAt((int) (Math.random() * ((double) RANDOM_CHARS.length()))); char rnd = RANDOM_CHARS.charAt((int) (Math.random() * ((double) RANDOM_CHARS.length())));

View File

@ -491,7 +491,7 @@ public class TileEntityScreen extends BlockEntity {
} }
private static void checkLaserUserRights(Screen scr) { private static void checkLaserUserRights(Screen scr) {
if (scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.CLICK) == 0) if (scr.laserUser != null && (scr.rightsFor(scr.laserUser) & ScreenRights.INTERACT) == 0)
scr.laserUser = null; scr.laserUser = null;
} }
@ -586,7 +586,6 @@ public class TileEntityScreen extends BlockEntity {
} }
public void handleJSRequest(ServerPlayer src, BlockSide side, int reqId, JSServerRequest req, Object[] data) { public void handleJSRequest(ServerPlayer src, BlockSide side, int reqId, JSServerRequest req, Object[] data) {
// TODO:
if (level.isClientSide) { if (level.isClientSide) {
Log.error("Called handleJSRequest client-side"); Log.error("Called handleJSRequest client-side");
return; return;
@ -1058,7 +1057,7 @@ public class TileEntityScreen extends BlockEntity {
return null; return null;
} }
if ((scr.rightsFor(ply) & ScreenRights.CLICK) == 0) if ((scr.rightsFor(ply) & ScreenRights.INTERACT) == 0)
return null; //Don't output an error, it can 'legally' happen return null; //Don't output an error, it can 'legally' happen
if (scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matchesLaserMouse)) { if (scr.upgrades.stream().noneMatch(DefaultUpgrade.LASERMOUSE::matchesLaserMouse)) {

View File

@ -3,6 +3,7 @@ package net.montoyo.wd.net;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.montoyo.wd.utilities.Vector3i; import net.montoyo.wd.utilities.Vector3i;
import java.util.Arrays;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -54,9 +55,9 @@ public class BufferUtils {
for (T element : elements) writer.accept(element); for (T element : elements) writer.accept(element);
} }
public static <T> T[] readArray(FriendlyByteBuf buf, Supplier<T> reader) { public static <T> T[] readArray(FriendlyByteBuf buf, T[] array, Supplier<T> reader) {
//noinspection unchecked //noinspection unchecked
T[] ts = (T[]) new Object[readUShort(buf)]; T[] ts = (T[]) Arrays.copyOf(array, readUShort(buf), array.getClass());
for (int i = 0; i < ts.length; i++) ts[i] = reader.get(); for (int i = 0; i < ts.length; i++) ts[i] = reader.get();
return ts; return ts;
} }

View File

@ -36,10 +36,11 @@ public class S2CMessageACResult extends Packet {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
ctx.enqueueWork(() -> { if (checkClient(ctx)) {
WebDisplays.PROXY.onAutocompleteResult(result); ctx.enqueueWork(() -> {
}); WebDisplays.PROXY.onAutocompleteResult(result);
ctx.setPacketHandled(true); });
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -91,45 +91,47 @@ public class S2CMessageAddScreen extends Packet {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
ctx.enqueueWork(() -> { if (checkClient(ctx)) {
Level lvl = (Level) WebDisplays.PROXY.getWorld(ctx); ctx.enqueueWork(() -> {
BlockEntity te = lvl.getBlockEntity(pos.toBlock()); Level lvl = (Level) WebDisplays.PROXY.getWorld(ctx);
if (!(te instanceof TileEntityScreen)) { BlockEntity te = lvl.getBlockEntity(pos.toBlock());
lvl.setBlockAndUpdate(pos.toBlock(), lvl.getBlockState(pos.toBlock()).setValue(hasTE, true));
te = lvl.getBlockEntity(pos.toBlock());
if (!(te instanceof TileEntityScreen)) { if (!(te instanceof TileEntityScreen)) {
if (clear) lvl.setBlockAndUpdate(pos.toBlock(), lvl.getBlockState(pos.toBlock()).setValue(hasTE, true));
Log.error("CMessageAddScreen: Can't add screen to invalid tile entity at %s", pos.toString()); te = lvl.getBlockEntity(pos.toBlock());
return; if (!(te instanceof TileEntityScreen)) {
} if (clear)
} Log.error("CMessageAddScreen: Can't add screen to invalid tile entity at %s", pos.toString());
TileEntityScreen tes = (TileEntityScreen) te; return;
if (clear) }
tes.clear();
for (TileEntityScreen.Screen entry : screens) {
TileEntityScreen.Screen scr = tes.addScreen(entry.side, entry.size, entry.resolution, null, false);
scr.rotation = entry.rotation;
String webUrl;
try {
webUrl = TileEntityScreen.url(entry.url);
} catch (IOException e) {
throw new RuntimeException(e);
} }
scr.url = webUrl; TileEntityScreen tes = (TileEntityScreen) te;
scr.owner = entry.owner; if (clear)
scr.upgrades = entry.upgrades; tes.clear();
if (scr.browser != null) for (TileEntityScreen.Screen entry : screens) {
scr.browser.loadURL(webUrl); TileEntityScreen.Screen scr = tes.addScreen(entry.side, entry.size, entry.resolution, null, false);
} scr.rotation = entry.rotation;
}); String webUrl;
ctx.setPacketHandled(true); try {
webUrl = TileEntityScreen.url(entry.url);
} catch (IOException e) {
throw new RuntimeException(e);
}
scr.url = webUrl;
scr.owner = entry.owner;
scr.upgrades = entry.upgrades;
if (scr.browser != null)
scr.browser.loadURL(webUrl);
}
});
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -46,12 +46,14 @@ public class S2CMessageCloseGui extends Packet {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
ctx.enqueueWork(() -> { if (checkClient(ctx)) {
if (blockSide == null) ctx.enqueueWork(() -> {
Arrays.stream(BlockSide.values()).forEach(s -> WebDisplays.PROXY.closeGui(blockPos, s)); if (blockSide == null)
else Arrays.stream(BlockSide.values()).forEach(s -> WebDisplays.PROXY.closeGui(blockPos, s));
WebDisplays.PROXY.closeGui(blockPos, blockSide); else
}); WebDisplays.PROXY.closeGui(blockPos, blockSide);
ctx.setPacketHandled(true); });
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -80,16 +80,18 @@ public class S2CMessageJSResponse extends Packet {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
ctx.enqueueWork(() -> { if (checkClient(ctx)) {
try { ctx.enqueueWork(() -> {
if (success) try {
WebDisplays.PROXY.handleJSResponseSuccess(id, type, data); if (success)
else WebDisplays.PROXY.handleJSResponseSuccess(id, type, data);
WebDisplays.PROXY.handleJSResponseError(id, type, errCode, errString); else
} catch (Throwable t) { WebDisplays.PROXY.handleJSResponseError(id, type, errCode, errString);
Log.warningEx("Could not handle JS response", t); } catch (Throwable t) {
} Log.warningEx("Could not handle JS response", t);
}); }
ctx.setPacketHandled(true); });
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -37,7 +37,9 @@ public class S2CMessageOpenGui extends Packet {
} }
public void handle(NetworkEvent.Context context) { public void handle(NetworkEvent.Context context) {
context.enqueueWork(() -> WebDisplays.PROXY.displayGui(data)); if (checkClient(context)) {
context.setPacketHandled(true); context.enqueueWork(() -> WebDisplays.PROXY.displayGui(data));
context.setPacketHandled(true);
}
} }
} }

View File

@ -234,21 +234,22 @@ public class S2CMessageScreenUpdate extends Packet {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
ctx.enqueueWork(() -> { if (checkClient(ctx)) {
BlockGetter level = WebDisplays.PROXY.getWorld(ctx); ctx.enqueueWork(() -> {
if (level instanceof Level level1) BlockGetter level = WebDisplays.PROXY.getWorld(ctx);
// ensure that the TE exists if (level instanceof Level level1)
level1.setBlock( // ensure that the TE exists
pos.toBlock(), level1.setBlock(
level.getBlockState(pos.toBlock()).setValue(BlockScreen.hasTE, true),11 pos.toBlock(),
); level.getBlockState(pos.toBlock()).setValue(BlockScreen.hasTE, true),11
BlockEntity te = level.getBlockEntity(pos.toBlock()); );
if(!(te instanceof TileEntityScreen)) { BlockEntity te = level.getBlockEntity(pos.toBlock());
Log.error("CMessageScreenUpdate: TileEntity at %s is not a screen!", pos.toString()); if(!(te instanceof TileEntityScreen)) {
return; Log.error("CMessageScreenUpdate: TileEntity at %s is not a screen!", pos.toString());
} return;
}
TileEntityScreen tes = (TileEntityScreen) te; TileEntityScreen tes = (TileEntityScreen) te;
switch (action) { switch (action) {
case UPDATE_URL -> { case UPDATE_URL -> {
@ -274,8 +275,9 @@ public class S2CMessageScreenUpdate extends Packet {
case UPDATE_AUTO_VOL -> tes.setAutoVolume(side, autoVolume); case UPDATE_AUTO_VOL -> tes.setAutoVolume(side, autoVolume);
default -> Log.warning("Caught invalid CMessageScreenUpdate with action ID %d", action); default -> Log.warning("Caught invalid CMessageScreenUpdate with action ID %d", action);
} }
}); });
ctx.setPacketHandled(true); ctx.setPacketHandled(true);
}
} }
} }

View File

@ -35,7 +35,7 @@ public class S2CMessageServerInfo extends Packet {
try { try {
WebDisplays.PROXY.setMiniservClientPort(miniservPort); WebDisplays.PROXY.setMiniservClientPort(miniservPort);
C2SMessageMiniservConnect message = Client.getInstance().beginConnection(); C2SMessageMiniservConnect message = Client.getInstance().beginConnection();
respondLater(ctx, message); respond(ctx, message);
ctx.setPacketHandled(true); ctx.setPacketHandled(true);
} catch (Throwable err) { } catch (Throwable err) {
err.printStackTrace(); err.printStackTrace();

View File

@ -18,7 +18,6 @@ import net.montoyo.wd.utilities.NameUUIDPair;
import java.util.Arrays; import java.util.Arrays;
public class C2SMessageACQuery extends Packet implements Runnable { public class C2SMessageACQuery extends Packet implements Runnable {
private ServerPlayer player; private ServerPlayer player;
private String beginning; private String beginning;
private boolean matchExact; private boolean matchExact;
@ -28,11 +27,11 @@ public class C2SMessageACQuery extends Packet implements Runnable {
matchExact = exact; matchExact = exact;
} }
public C2SMessageACQuery(FriendlyByteBuf buf) { public C2SMessageACQuery(FriendlyByteBuf buf) {
super(buf); super(buf);
beginning = buf.readUtf(); beginning = buf.readUtf();
matchExact = buf.readBoolean(); matchExact = buf.readBoolean();
} }
@Override @Override
public void write(FriendlyByteBuf buf) { public void write(FriendlyByteBuf buf) {
@ -56,9 +55,10 @@ public class C2SMessageACQuery extends Packet implements Runnable {
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
player = ctx.getSender(); if (checkServer(ctx)) {
ctx.enqueueWork(this); player = ctx.getSender();
ctx.setPacketHandled(true); ctx.enqueueWork(this);
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -19,66 +19,68 @@ import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i; import net.montoyo.wd.utilities.Vector3i;
public class C2SMessageRedstoneCtrl extends Packet implements Runnable { public class C2SMessageRedstoneCtrl extends Packet implements Runnable {
private Player player; private Player player;
private Vector3i pos; private Vector3i pos;
private String risingEdgeURL; private String risingEdgeURL;
private String fallingEdgeURL; private String fallingEdgeURL;
public C2SMessageRedstoneCtrl() { public C2SMessageRedstoneCtrl() {
} }
public C2SMessageRedstoneCtrl(Vector3i p, String r, String f) { public C2SMessageRedstoneCtrl(Vector3i p, String r, String f) {
pos = p; pos = p;
risingEdgeURL = r; risingEdgeURL = r;
fallingEdgeURL = f; fallingEdgeURL = f;
} }
public C2SMessageRedstoneCtrl(FriendlyByteBuf buf) { public C2SMessageRedstoneCtrl(FriendlyByteBuf buf) {
super(buf); super(buf);
pos = new Vector3i(buf); pos = new Vector3i(buf);
risingEdgeURL = buf.readUtf(); risingEdgeURL = buf.readUtf();
fallingEdgeURL = buf.readUtf(); fallingEdgeURL = buf.readUtf();
} }
@Override @Override
public void run() { public void run() {
Level world = player.level; Level world = player.level;
BlockPos blockPos = pos.toBlock(); BlockPos blockPos = pos.toBlock();
final double maxRange = player.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue(); final double maxRange = player.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue();
if(player.distanceToSqr(blockPos.getX(), blockPos.getY(), blockPos.getZ()) > maxRange * maxRange) if (player.distanceToSqr(blockPos.getX(), blockPos.getY(), blockPos.getZ()) > maxRange * maxRange)
return; return;
BlockEntity te = world.getBlockEntity(blockPos); BlockEntity te = world.getBlockEntity(blockPos);
if(te == null || !(te instanceof TileEntityRedCtrl)) if (te == null || !(te instanceof TileEntityRedCtrl))
return; return;
TileEntityRedCtrl redCtrl = (TileEntityRedCtrl) te; TileEntityRedCtrl redCtrl = (TileEntityRedCtrl) te;
if(!redCtrl.isScreenChunkLoaded()) { if (!redCtrl.isScreenChunkLoaded()) {
Util.toast(player, "chunkUnloaded"); Util.toast(player, "chunkUnloaded");
return; return;
} }
TileEntityScreen tes = redCtrl.getConnectedScreen(); TileEntityScreen tes = redCtrl.getConnectedScreen();
if(tes == null) if (tes == null)
return; return;
if((tes.getScreen(redCtrl.getScreenSide()).rightsFor(player) & ScreenRights.CHANGE_URL) == 0) if ((tes.getScreen(redCtrl.getScreenSide()).rightsFor(player) & ScreenRights.CHANGE_URL) == 0)
return; return;
redCtrl.setURLs(risingEdgeURL, fallingEdgeURL); redCtrl.setURLs(risingEdgeURL, fallingEdgeURL);
} }
@Override @Override
public void write(FriendlyByteBuf buf) { public void write(FriendlyByteBuf buf) {
pos.writeTo(buf); pos.writeTo(buf);
buf.writeUtf(risingEdgeURL); buf.writeUtf(risingEdgeURL);
buf.writeUtf(fallingEdgeURL); buf.writeUtf(fallingEdgeURL);
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
player = ctx.getSender(); if (checkServer(ctx)) {
ctx.enqueueWork(this); player = ctx.getSender();
ctx.setPacketHandled(true); ctx.enqueueWork(this);
} ctx.setPacketHandled(true);
}
}
} }

View File

@ -6,369 +6,176 @@ package net.montoyo.wd.net.server_bound;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.block.BlockPeripheral; import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.core.DefaultPeripheral; import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.controls.ScreenControlRegistry;
import net.montoyo.wd.controls.builtin.*;
import net.montoyo.wd.core.JSServerRequest; import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.core.MissingPermissionException; import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen; import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.BlockInit; import net.montoyo.wd.net.BufferUtils;
import net.montoyo.wd.net.Packet; import net.montoyo.wd.net.Packet;
import net.montoyo.wd.utilities.*; import net.montoyo.wd.utilities.*;
import java.io.IOException;
// TODO: this is a mess; a registry based approach would likely be more readable // TODO: this is a mess; a registry based approach would likely be more readable
public class C2SMessageScreenCtrl extends Packet implements Runnable { public class C2SMessageScreenCtrl extends Packet {
public static final int CTRL_SET_URL = 0; @Deprecated(forRemoval = true)
public static final int CTRL_SHUT_DOWN = 1; public static final int CTRL_LASER_MOVE = 0;
public static final int CTRL_ADD_FRIEND = 2; @Deprecated(forRemoval = true)
public static final int CTRL_REMOVE_FRIEND = 3; public static final int CTRL_LASER_UP = 0;
public static final int CTRL_SET_RIGHTS = 4; @Deprecated(forRemoval = true)
public static final int CTRL_SET_RESOLUTION = 5; public static final int CTRL_LASER_DOWN = 0;
public static final int CTRL_TYPE = 6; @Deprecated(forRemoval = true)
public static final int CTRL_REMOVE_UPGRADE = 7; public static final int CTRL_SET_RESOLUTION = 0;
public static final int CTRL_LASER_DOWN = 8;
public static final int CTRL_LASER_MOVE = 9;
public static final int CTRL_LASER_UP = 10;
public static final int CTRL_JS_REQUEST = 11;
public static final int CTRL_SET_ROTATION = 12;
public static final int CTRL_SET_URL_REMOTE = 13;
public static final int CTRL_SET_AUTO_VOL = 14;
private int ctrl; ScreenControl control;
private ResourceLocation dim; BlockPos pos;
private Vector3i pos; BlockSide side;
private BlockSide side;
private String url;
private NameUUIDPair friend;
private ServerPlayer player;
private int friendRights;
private int otherRights;
private Vector2i vec2i;
private String text;
private BlockPos soundPos;
private ItemStack toRemove;
private int jsReqID;
private JSServerRequest jsReqType;
private Object[] jsReqData;
private Rotation rotation;
private Vector3i remoteLoc;
private boolean autoVol;
public C2SMessageScreenCtrl() { public C2SMessageScreenCtrl() {
} }
public C2SMessageScreenCtrl(TileEntityScreen screen, BlockSide side, ScreenControl control) {
this.pos = screen.getBlockPos();
this.side = side;
this.control = control;
}
protected static C2SMessageScreenCtrl base(TileEntityScreen screen, BlockSide side) {
C2SMessageScreenCtrl packet = new C2SMessageScreenCtrl();
packet.pos = screen.getBlockPos();
packet.side = side;
return packet;
}
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl setURL(TileEntityScreen tes, BlockSide side, String url, Vector3i remoteLocation) { public static C2SMessageScreenCtrl setURL(TileEntityScreen tes, BlockSide side, String url, Vector3i remoteLocation) {
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl(); C2SMessageScreenCtrl ret = base(tes, side);
ret.ctrl = (remoteLocation == null) ? CTRL_SET_URL : CTRL_SET_URL_REMOTE; ret.control = new SetURLControl(url, remoteLocation);
ret.dim = tes.getLevel().dimension().location();
ret.pos = new Vector3i(tes.getBlockPos());
ret.side = side;
ret.url = url;
if (remoteLocation != null)
ret.remoteLoc = remoteLocation;
return ret; return ret;
} }
@Deprecated(forRemoval = true)
public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, NameUUIDPair friend, boolean del) { public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, NameUUIDPair friend, boolean del) {
ctrl = del ? CTRL_REMOVE_FRIEND : CTRL_ADD_FRIEND; this(tes, side, new ModifyFriendListControl(friend, !del));
dim = tes.getLevel().dimension().location();
pos = new Vector3i(tes.getBlockPos());
this.side = side;
this.friend = friend;
} }
@Deprecated(forRemoval = true)
public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, int fr, int or) { public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, int fr, int or) {
ctrl = CTRL_SET_RIGHTS; this(tes, side, new ManageRightsAndUpdgradesControl(fr, or));
dim = tes.getLevel().dimension().location();
pos = new Vector3i(tes.getBlockPos());
this.side = side;
friendRights = fr;
otherRights = or;
} }
@Deprecated(forRemoval = true)
public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, ItemStack toRem) { public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, ItemStack toRem) {
ctrl = CTRL_REMOVE_UPGRADE; this(tes, side, new ManageRightsAndUpdgradesControl(toRem));
dim = tes.getLevel().dimension().location();
pos = new Vector3i(tes.getBlockPos());
this.side = side;
toRemove = toRem;
} }
@Deprecated(forRemoval = true)
public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, Rotation rot) { public C2SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, Rotation rot) {
ctrl = CTRL_SET_ROTATION; this(tes, side, new ScreenModifyControl(rot));
dim = tes.getLevel().dimension().location();
pos = new Vector3i(tes.getBlockPos());
this.side = side;
rotation = rot;
}
public static C2SMessageScreenCtrl type(TileEntityScreen tes, BlockSide side, String text, BlockPos soundPos) {
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl();
ret.ctrl = CTRL_TYPE;
ret.pos = new Vector3i(tes.getBlockPos());
ret.dim = tes.getLevel().dimension().location();
ret.side = side;
ret.text = text;
ret.soundPos = soundPos;
return ret;
} }
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl vec2(TileEntityScreen tes, BlockSide side, int ctrl, Vector2i vec) { public static C2SMessageScreenCtrl vec2(TileEntityScreen tes, BlockSide side, int ctrl, Vector2i vec) {
if (!isVec2Ctrl(ctrl)) throw new RuntimeException("Moved: look into ScreenControlRegistry");
throw new RuntimeException("Called SMessageScreenCtrl.vec2() with non-vec2 control message " + ctrl); }
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl();
ret.ctrl = ctrl;
ret.pos = new Vector3i(tes.getBlockPos());
ret.dim = tes.getLevel().dimension().location();
ret.side = side;
ret.vec2i = vec;
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl resolution(TileEntityScreen tes, BlockSide side, Vector2i vec) {
C2SMessageScreenCtrl ret = base(tes, side);
ret.control = new ScreenModifyControl(vec);
return ret; return ret;
} }
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl type(TileEntityScreen tes, BlockSide side, String text, BlockPos soundPos) {
C2SMessageScreenCtrl ret = base(tes, side);
ret.control = new KeyTypedControl(text, soundPos);
return ret;
}
public static C2SMessageScreenCtrl laserMove(TileEntityScreen tes, BlockSide side, Vector2i vec) {
C2SMessageScreenCtrl ret = base(tes, side);
ret.control = new LaserControl(LaserControl.ControlType.MOVE, vec);
return ret;
}
public static C2SMessageScreenCtrl laserDown(TileEntityScreen tes, BlockSide side, Vector2i vec) {
C2SMessageScreenCtrl ret = base(tes, side);
ret.control = new LaserControl(LaserControl.ControlType.MOVE, vec);
return ret;
}
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl laserUp(TileEntityScreen tes, BlockSide side) { public static C2SMessageScreenCtrl laserUp(TileEntityScreen tes, BlockSide side) {
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl(); C2SMessageScreenCtrl ret = base(tes, side);
ret.ctrl = CTRL_LASER_UP; ret.control = new LaserControl(LaserControl.ControlType.UP, null);
ret.pos = new Vector3i(tes.getBlockPos());
ret.dim = tes.getLevel().dimension().location();
ret.side = side;
return ret; return ret;
} }
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl jsRequest(TileEntityScreen tes, BlockSide side, int reqId, JSServerRequest reqType, Object... data) { public static C2SMessageScreenCtrl jsRequest(TileEntityScreen tes, BlockSide side, int reqId, JSServerRequest reqType, Object... data) {
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl(); C2SMessageScreenCtrl ret = base(tes, side);
ret.ctrl = CTRL_JS_REQUEST; ret.control = new JSRequestControl(reqId, reqType, data);
ret.pos = new Vector3i(tes.getBlockPos());
ret.dim = tes.getLevel().dimension().location();
ret.side = side;
ret.jsReqID = reqId;
ret.jsReqType = reqType;
ret.jsReqData = data;
return ret; return ret;
} }
@Deprecated(forRemoval = true)
public static C2SMessageScreenCtrl autoVol(TileEntityScreen tes, BlockSide side, boolean av) { public static C2SMessageScreenCtrl autoVol(TileEntityScreen tes, BlockSide side, boolean av) {
C2SMessageScreenCtrl ret = new C2SMessageScreenCtrl(); C2SMessageScreenCtrl ret = base(tes, side);
ret.ctrl = CTRL_SET_AUTO_VOL; ret.control = new AutoVolumeControl(av);
ret.pos = new Vector3i(tes.getBlockPos());
ret.dim = tes.getLevel().dimension().location();
ret.side = side;
ret.autoVol = av;
return ret; return ret;
} }
private static boolean isVec2Ctrl(int msg) {
return msg == CTRL_SET_RESOLUTION || msg == CTRL_LASER_DOWN || msg == CTRL_LASER_MOVE;
}
public C2SMessageScreenCtrl(FriendlyByteBuf buf) { public C2SMessageScreenCtrl(FriendlyByteBuf buf) {
super(buf); super(buf);
decode(buf);
}
public void decode(FriendlyByteBuf buf) { pos = buf.readBlockPos();
C2SMessageScreenCtrl message = this; side = (BlockSide) BufferUtils.readEnum(buf, (i) -> BlockSide.values()[i], (byte) 1);
message.ctrl = buf.readByte();
message.dim = buf.readResourceLocation();
message.pos = new Vector3i(buf);
message.side = BlockSide.fromInt(buf.readByte());
if (message.ctrl == CTRL_SET_URL) this.control = ScreenControlRegistry.parse(buf);
message.url = buf.readUtf();
else if (message.ctrl == CTRL_ADD_FRIEND || message.ctrl == CTRL_REMOVE_FRIEND)
message.friend = new NameUUIDPair(buf);
else if (message.ctrl == CTRL_SET_RIGHTS) {
message.friendRights = buf.readByte();
message.otherRights = buf.readByte();
} else if (isVec2Ctrl(message.ctrl))
message.vec2i = new Vector2i(buf);
else if (message.ctrl == CTRL_TYPE) {
message.text = buf.readUtf();
int sx = buf.readInt();
int sy = buf.readInt();
int sz = buf.readInt();
message.soundPos = new BlockPos(sx, sy, sz);
} else if (message.ctrl == CTRL_REMOVE_UPGRADE)
message.toRemove = buf.readItem();
else if (message.ctrl == CTRL_JS_REQUEST) {
message.jsReqID = buf.readInt();
message.jsReqType = JSServerRequest.fromID(buf.readByte());
if (message.jsReqType != null)
message.jsReqData = message.jsReqType.deserialize(buf);
} else if (message.ctrl == CTRL_SET_ROTATION)
message.rotation = Rotation.values()[buf.readByte() & 3];
else if (message.ctrl == CTRL_SET_URL_REMOTE) {
message.url = buf.readUtf();
message.remoteLoc = new Vector3i(buf);
} else if (message.ctrl == CTRL_SET_AUTO_VOL)
message.autoVol = buf.readBoolean();
} }
@Override @Override
public void write(FriendlyByteBuf buf) { public void write(FriendlyByteBuf buf) {
buf.writeByte(ctrl); buf.writeBlockPos(pos);
buf.writeResourceLocation(dim); BufferUtils.writeEnum(buf, side, (byte) 1);
pos.writeTo(buf);
buf.writeByte(side.ordinal());
if (ctrl == CTRL_SET_URL) buf.writeUtf(control.getId().toString());
buf.writeUtf(url); control.write(buf);
else if (ctrl == CTRL_ADD_FRIEND || ctrl == CTRL_REMOVE_FRIEND)
friend.writeTo(buf);
else if (ctrl == CTRL_SET_RIGHTS) {
buf.writeByte(friendRights);
buf.writeByte(otherRights);
} else if (isVec2Ctrl(ctrl))
vec2i.writeTo(buf);
else if (ctrl == CTRL_TYPE) {
buf.writeUtf(text);
buf.writeInt(soundPos.getX());
buf.writeInt(soundPos.getY());
buf.writeInt(soundPos.getZ());
} else if (ctrl == CTRL_REMOVE_UPGRADE)
buf.writeItem(toRemove);
else if (ctrl == CTRL_JS_REQUEST) {
buf.writeInt(jsReqID);
buf.writeByte(jsReqType.ordinal());
if (!jsReqType.serialize(buf, jsReqData))
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + jsReqType);
} else if (ctrl == CTRL_SET_ROTATION)
buf.writeByte(rotation.ordinal());
else if (ctrl == CTRL_SET_URL_REMOTE) {
buf.writeUtf(url);
remoteLoc.writeTo(buf);
} else if (ctrl == CTRL_SET_AUTO_VOL)
buf.writeBoolean(autoVol);
} }
@Override public void checkPermission(ServerPlayer sender, TileEntityScreen scr, int right) throws MissingPermissionException {
public void run() { int prights = scr.getScreen(side).rightsFor(sender);
if (side == null) {
Log.warning("Caught invalid packet from %s (UUID %s) referencing an invalid block side", player.getName(), player.getGameProfile().getId().toString());
return;
}
try {
runUnsafe();
} catch (MissingPermissionException e) {
Log.errorEx("I have reasons to believe %s (UUID %s) is a hacker, but don't take my word for it...", e, e.getPlayer().getName(), e.getPlayer().getGameProfile().getId().toString());
}
}
private void checkPermission(TileEntityScreen scr, int right) throws MissingPermissionException {
int prights = scr.getScreen(side).rightsFor(player);
if ((prights & right) == 0) if ((prights & right) == 0)
throw new MissingPermissionException(right, player); throw new MissingPermissionException(right, sender);
}
private void runUnsafe() throws MissingPermissionException {
Level world = player.level;
BlockPos bp = pos.toBlock();
if (!world.dimension().location().equals(dim))
return; //Out of range (dimension mismatch)
if (ctrl == CTRL_SET_URL_REMOTE) {
double reachDist = player.getAttributeValue(ForgeMod.REACH_DISTANCE.get());
BlockPos blockPos = remoteLoc.toBlock();
if (player.distanceToSqr(blockPos.getX(), blockPos.getY(), blockPos.getZ()) > reachDist * reachDist)
return; //Out of range (player reach distance)
BlockState bs = world.getBlockState(blockPos);
if (bs.getBlock() != BlockInit.blockServer.get() && bs.getBlock() != BlockInit.blockRControl.get() &&
bs.getBlock() != BlockInit.blockKeyBoard.get() && bs.getBlock() != BlockInit.blockRedControl.get()
&& bs.getValue(BlockPeripheral.type) != DefaultPeripheral.REMOTE_CONTROLLER)
return; //I call it hax...
} else if (player.distanceToSqr(bp.getX(), bp.getY(), bp.getZ()) > (128 * 128))
return; //Out of range (range problem)
BlockEntity te = world.getBlockEntity(bp);
if (te == null || !(te instanceof TileEntityScreen)) {
Log.error("TileEntity at %s is not a screen; can't control it!", pos.toString());
return;
}
TileEntityScreen tes = (TileEntityScreen) te;
if (ctrl == CTRL_SET_URL || ctrl == CTRL_SET_URL_REMOTE) {
checkPermission(tes, ScreenRights.CHANGE_URL);
try {
tes.setScreenURL(side, url);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else if (ctrl == CTRL_SHUT_DOWN) {
//TODO
//checkPermission(tes, ScreenRights.CHANGE_URL);
//tes.removeScreen(side);
} else if (ctrl == CTRL_ADD_FRIEND) {
checkPermission(tes, ScreenRights.MANAGE_FRIEND_LIST);
tes.addFriend(player, side, friend);
} else if (ctrl == CTRL_REMOVE_FRIEND) {
checkPermission(tes, ScreenRights.MANAGE_FRIEND_LIST);
tes.removeFriend(player, side, friend);
} else if (ctrl == CTRL_SET_RIGHTS) {
TileEntityScreen.Screen scr = tes.getScreen(side);
if (scr != null) {
int fr = scr.owner.uuid.equals(player.getGameProfile().getId()) ? friendRights : scr.friendRights;
int or = (scr.rightsFor(player) & ScreenRights.MANAGE_OTHER_RIGHTS) == 0 ? scr.otherRights : otherRights;
if (scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
} else if (ctrl == CTRL_SET_RESOLUTION) {
checkPermission(tes, ScreenRights.CHANGE_RESOLUTION);
tes.setResolution(side, vec2i);
} else if (ctrl == CTRL_TYPE) {
checkPermission(tes, ScreenRights.CLICK);
tes.type(side, text, soundPos);
} else if (ctrl == CTRL_REMOVE_UPGRADE) {
checkPermission(tes, ScreenRights.MANAGE_UPGRADES);
tes.removeUpgrade(side, toRemove, player);
} else if (ctrl == CTRL_LASER_DOWN || ctrl == CTRL_LASER_MOVE)
tes.laserDownMove(side, player, vec2i, ctrl == CTRL_LASER_DOWN);
else if (ctrl == CTRL_LASER_UP)
tes.laserUp(side, player);
else if (ctrl == CTRL_JS_REQUEST) {
if (jsReqType == null || jsReqData == null)
Log.warning("Caught invalid JS request from player %s (UUID %s)", player.getName(), player.getGameProfile().getId().toString());
else
tes.handleJSRequest(player, side, jsReqID, jsReqType, jsReqData);
} else if (ctrl == CTRL_SET_ROTATION) {
checkPermission(tes, ScreenRights.CHANGE_RESOLUTION);
tes.setRotation(side, rotation);
} else if (ctrl == CTRL_SET_AUTO_VOL) {
checkPermission(tes, ScreenRights.MANAGE_UPGRADES); //because why not
tes.setAutoVolume(side, autoVol);
} else
Log.warning("Caught SMessageScreenCtrl with invalid control ID %d from player %s (UUID %s)", ctrl, player.getName(), player.getGameProfile().getId().toString());
} }
public void handle(NetworkEvent.Context ctx) { public void handle(NetworkEvent.Context ctx) {
player = ctx.getSender(); if (checkServer(ctx)) {
ctx.enqueueWork(this); ctx.enqueueWork(() -> {
ctx.setPacketHandled(true); try {
Level level = (Level) WebDisplays.PROXY.getWorld(ctx);
BlockEntity be = level.getBlockEntity(pos);
if (be instanceof TileEntityScreen tes) {
control.handleServer(pos, side, tes, ctx, (perm) -> {
try {
checkPermission(ctx.getSender(), tes, perm);
return true;
} catch (Throwable ignored) {
return false;
}
});
}
} catch (MissingPermissionException e) {
}
});
ctx.setPacketHandled(true);
}
} }
} }

View File

@ -81,6 +81,7 @@ public enum VideoType {
return String.format(format, vid); return String.format(format, vid);
} }
// TODO: timestamp stuff
@Nonnull @Nonnull
public String getVolumeJSQuery(int volInt, int volFrac) { public String getVolumeJSQuery(int volInt, int volFrac) {
return (new StringBuilder(volumeCap)).append(volumePrefix).append(volInt).append('.').append(volFrac).append(volumeSuffix).toString(); return (new StringBuilder(volumeCap)).append(volumePrefix).append(volInt).append('.').append(volFrac).append(volumeSuffix).toString();

View File

@ -2,12 +2,12 @@
"itemGroup.webdisplays": "§5Web Displays", "itemGroup.webdisplays": "§5Web Displays",
"block.webdisplays.screen": "Web Screen", "block.webdisplays.screen": "Web Screen",
"block.webdisplays.peripheral": "Peripheral", "block.webdisplays.peripheral": "Peripheral",
"block.webdisplays.peripheral.keyboard": "Keyboard", "block.webdisplays.kb_left": "Keyboard",
"block.webdisplays.peripheral.remotectrl": "Remote Controller", "block.webdisplays.rctrl": "Remote Controller",
"block.webdisplays.peripheral.ccinterface": "ComputerCraft Interface", "block.webdisplays.ccinterface": "ComputerCraft Interface",
"block.webdisplays.peripheral.cointerface": "OpenComputers Interface", "block.webdisplays.cointerface": "OpenComputers Interface",
"block.webdisplays.peripheral.redstonectrl": "Redstone Controller", "block.webdisplays.redctrl": "Redstone Controller",
"block.webdisplays.peripheral.server": "Server", "block.webdisplays.server": "Server",
"item.webdisplays.screencfg": "Screen Configurator", "item.webdisplays.screencfg": "Screen Configurator",
"item.webdisplays.ownerthief": "Ownership Thief [ADMIN]", "item.webdisplays.ownerthief": "Ownership Thief [ADMIN]",
"item.webdisplays.linker": "Linking Tool", "item.webdisplays.linker": "Linking Tool",
@ -24,10 +24,10 @@
"item.webdisplays.minepad": "minePad", "item.webdisplays.minepad": "minePad",
"item.webdisplays.minepad2": "minePad 2", "item.webdisplays.minepad2": "minePad 2",
"item.webdisplays.upgrade": "Screen Upgrade", "item.webdisplays.upgrade": "Screen Upgrade",
"item.webdisplays.upgrade.lasermouse": "Laser Sensor", "item.webdisplays.upgrade_lasermouse": "Laser Sensor",
"item.webdisplays.upgrade.redinput": "Redstone Input Port", "item.webdisplays.upgrade_redinput": "Redstone Input Port",
"item.webdisplays.upgrade.redoutput": "Redstone Output Port", "item.webdisplays.upgrade_redoutput": "Redstone Output Port",
"item.webdisplays.upgrade.gps": "GPS Module", "item.webdisplays.upgrade_gps": "GPS Module",
"item.webdisplays.laserpointer": "Laser Pointer", "item.webdisplays.laserpointer": "Laser Pointer",
"item.webdisplays.advicon": "Advancement Icon", "item.webdisplays.advicon": "Advancement Icon",
"item.webdisplays.advicon.wd": "WebDisplays", "item.webdisplays.advicon.wd": "WebDisplays",