diff --git a/build.gradle b/build.gradle index dae4d1f..ae4e48c 100755 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.0-SNAPSHOT' + id 'fabric-loom' version '1.2-SNAPSHOT' id 'maven-publish' } @@ -17,12 +17,6 @@ repositories { maven { url = "https://api.modrinth.com/maven" } - maven { - url "https://cursemaven.com" - content { - includeGroup "curse.maven" - } - } flatDir { dirs("localMaven") } diff --git a/gradle.properties b/gradle.properties index 49c77cd..5e6e038 100755 --- a/gradle.properties +++ b/gradle.properties @@ -3,20 +3,20 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.19 - yarn_mappings=1.19+build.4 - loader_version=0.14.8 + minecraft_version=1.20.1 + yarn_mappings=1.20.1+build.2 + loader_version=0.14.21 # Mod Properties - mod_version = 1.5.0 + mod_version = 2.0.0-beta.1 maven_group = eu.midnightdust archives_base_name = picturesign # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.56.0+1.19 - midnightlib_version=1.0.0-fabric - videolib_version=0.2.0-mnd + fabric_version=0.83.1+1.20.1 + midnightlib_version=1.4.1-fabric + videolib_version=0.2.1-mnd vlcj_version=4.8.2 - iris_version=1.19.x-v1.2.5 + iris_version=1.6.4+1.20 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a2..59bc51a 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/localMaven/videolib-0.2.0-mnd.jar b/localMaven/videolib-0.2.1-mnd.jar similarity index 72% rename from localMaven/videolib-0.2.0-mnd.jar rename to localMaven/videolib-0.2.1-mnd.jar index f91c750..f5894bf 100644 Binary files a/localMaven/videolib-0.2.0-mnd.jar and b/localMaven/videolib-0.2.1-mnd.jar differ diff --git a/src/main/java/eu/midnightdust/picturesign/PictureSignClient.java b/src/main/java/eu/midnightdust/picturesign/PictureSignClient.java index 7ff92e1..28a4ce2 100755 --- a/src/main/java/eu/midnightdust/picturesign/PictureSignClient.java +++ b/src/main/java/eu/midnightdust/picturesign/PictureSignClient.java @@ -38,20 +38,22 @@ public class PictureSignClient implements ClientModInitializer { ClientBlockEntityEvents.BLOCK_ENTITY_UNLOAD.register((blockEntity, world) -> { if (PlatformFunctions.isModLoaded("videolib")) { BlockPos pos = blockEntity.getPos(); - Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()); + Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()+"_f"); VideoHandler.closePlayer(videoId); + Identifier videoId2 = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()+"_b"); + VideoHandler.closePlayer(videoId2); } }); ClientTickEvents.END_CLIENT_TICK.register(client -> { if (!PictureSignClient.BINDING_COPY_SIGN.isPressed()) return; PictureSignClient.BINDING_COPY_SIGN.setPressed(false); if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.BLOCK) return; - if (client.crosshairTarget.getType() == HitResult.Type.BLOCK && client.world.getBlockState(new BlockPos(client.crosshairTarget.getPos())).hasBlockEntity()) { - if (client.world.getBlockEntity(new BlockPos(client.crosshairTarget.getPos())) instanceof SignBlockEntity sign) { - clipboard[0] = sign.getTextOnRow(0, false).getString(); - clipboard[1] = sign.getTextOnRow(1, false).getString(); - clipboard[2] = sign.getTextOnRow(2, false).getString(); - clipboard[3] = sign.getTextOnRow(3, false).getString(); + if (client.crosshairTarget.getType() == HitResult.Type.BLOCK && client.world.getBlockState(BlockPos.ofFloored(client.crosshairTarget.getPos())).hasBlockEntity()) { + if (client.world.getBlockEntity(BlockPos.ofFloored(client.crosshairTarget.getPos())) instanceof SignBlockEntity sign) { + boolean front = sign.isPlayerFacingFront(client.player); + for (int i = 0; i < 4; i++) { + clipboard[i] = sign.getText(front).getMessage(i, false).getString(); + } } } }); diff --git a/src/main/java/eu/midnightdust/picturesign/config/PictureSignConfig.java b/src/main/java/eu/midnightdust/picturesign/config/PictureSignConfig.java index c8df3d2..c58d527 100755 --- a/src/main/java/eu/midnightdust/picturesign/config/PictureSignConfig.java +++ b/src/main/java/eu/midnightdust/picturesign/config/PictureSignConfig.java @@ -2,25 +2,45 @@ package eu.midnightdust.picturesign.config; import com.google.common.collect.Lists; import eu.midnightdust.lib.config.MidnightConfig; +import net.minecraft.client.gl.ShaderProgram; +import net.minecraft.client.render.GameRenderer; import java.util.List; +import java.util.function.Supplier; public class PictureSignConfig extends MidnightConfig { - @Entry public static boolean enabled = true; - @Entry public static boolean enableVideoSigns = true; - @Entry public static boolean translucency = false; - @Entry public static boolean helperUi = true; - @Entry public static boolean exceedVanillaLineLength = true; - @Entry public static boolean debug = false; - @Entry(min = 1, max = 10) public static int maxThreads = 4; - @Entry(min = 0, max = 4096) public static int signRenderDistance = 64; - @Entry public static boolean safeMode = true; - @Comment public static Comment ebeWarning; - @Comment public static Comment ebeWarning2; - @Entry public static List safeProviders = Lists.newArrayList("https://i.imgur.com/", "https://i.ibb.co/", "https://pictshare.net/", "https://iili.io/"); - @Entry public static MissingImageMode missingImageMode = MissingImageMode.BLACK; + public static final String general = "1general"; + private final static String advanced = "advanced"; + + @Entry(category = general) public static boolean enabled = true; + @Entry(category = general) public static boolean enableVideoSigns = true; + @Entry(category = general) public static boolean translucency = false; + @Entry(category = general) public static boolean fullBrightPicture = false; + @Entry(category = general) public static boolean helperUi = true; + @Entry(category = general) public static boolean exceedVanillaLineLength = true; + @Entry(category = advanced) public static boolean debug = false; + @Entry(min = 1, max = 10, isSlider = true, category = advanced) public static int maxThreads = 4; + @Entry(min = 0, max = 2048, isSlider = true, category = general) public static int signRenderDistance = 64; + @Entry(category = general) public static boolean safeMode = true; + @Entry(category = general) public static List safeProviders = Lists.newArrayList("https://i.imgur.com/", "https://i.ibb.co/", "https://pictshare.net/", "https://iili.io/", "https://vimeo.com/", "https://yewtu.be/"); + @Entry(category = general) public static String invidiousInstance = "yt.oelrichsgarcia.de"; + @Comment(category = general) public static Comment ebeWarning; + @Entry(category = advanced) public static MissingImageMode missingImageMode = MissingImageMode.BLACK; + @Entry(category = advanced) public static PictureShader pictureShader = PictureShader.PosColTexLight; public enum MissingImageMode { BLACK, MISSING_TEXTURE, TRANSPARENT } + public enum PictureShader { + PosColTexLight(GameRenderer::getPositionColorTexLightmapProgram), + RenderTypeCutout(GameRenderer::getRenderTypeCutoutProgram), + PosTex(GameRenderer::getPositionTexProgram), + PosColTex(GameRenderer::getPositionColorTexProgram), + PosTexCol(GameRenderer::getPositionTexColorProgram); + + PictureShader(Supplier program) { + this.program = program; + } + public final Supplier program; + } } diff --git a/src/main/java/eu/midnightdust/picturesign/mixin/MixinHangingSignBlockEntityRenderer.java b/src/main/java/eu/midnightdust/picturesign/mixin/MixinHangingSignBlockEntityRenderer.java new file mode 100755 index 0000000..f9b07a7 --- /dev/null +++ b/src/main/java/eu/midnightdust/picturesign/mixin/MixinHangingSignBlockEntityRenderer.java @@ -0,0 +1,40 @@ +package eu.midnightdust.picturesign.mixin; + +import eu.midnightdust.picturesign.config.PictureSignConfig; +import eu.midnightdust.picturesign.render.PictureSignRenderer; +import eu.midnightdust.picturesign.util.PictureSignType; +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(HangingSignBlockEntityRenderer.class) +public abstract class MixinHangingSignBlockEntityRenderer implements BlockEntityRenderer { + private static final MinecraftClient client = MinecraftClient.getInstance(); + PictureSignRenderer psRenderer = new PictureSignRenderer(); + + @Inject(at = @At("HEAD"), method = "render") + public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) { + if (PictureSignConfig.enabled) { + if (!PictureSignType.isType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, light, overlay, true); + if (!PictureSignType.isType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, light, overlay, false); + } + } + @Unique + @Override + public int getRenderDistance() { + return PictureSignConfig.signRenderDistance; + } + @Unique + @Override + public boolean rendersOutsideBoundingBox(SignBlockEntity sign) { + return PictureSignConfig.enabled && !PictureSignType.hasNoPicture(sign); + } +} diff --git a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntity.java b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntity.java index 11b55eb..5a406c4 100644 --- a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntity.java +++ b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntity.java @@ -21,8 +21,10 @@ public abstract class MixinSignBlockEntity extends BlockEntity { @Override @Unique public void markRemoved() { - Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()); + Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ() + "_f"); + Identifier videoId2 = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ() + "_b"); VideoHandler.closePlayer(videoId); + VideoHandler.closePlayer(videoId2); super.markRemoved(); } } diff --git a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntityRenderer.java b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntityRenderer.java index e59b9eb..9666239 100755 --- a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntityRenderer.java +++ b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignBlockEntityRenderer.java @@ -4,10 +4,12 @@ import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.render.PictureSignRenderer; import eu.midnightdust.picturesign.util.PictureSignType; import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.render.block.entity.SignBlockEntityRenderer; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -17,17 +19,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(SignBlockEntityRenderer.class) public abstract class MixinSignBlockEntityRenderer implements BlockEntityRenderer { + private static final MinecraftClient client = MinecraftClient.getInstance(); PictureSignRenderer psRenderer = new PictureSignRenderer(); @Inject(at = @At("HEAD"), method = "render") public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) { - if (PictureSignConfig.enabled && !PictureSignType.isType(sign, PictureSignType.NONE)) { - psRenderer.render(sign, matrixStack, light, overlay); + if (PictureSignConfig.enabled) { + if (!PictureSignType.isType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, light, overlay, true); + if (!PictureSignType.isType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, light, overlay, false); } } @Inject(at = @At("HEAD"), method = "shouldRender", cancellable = true) - private static void shouldRender(SignBlockEntity sign, int signColor, CallbackInfoReturnable cir) { - if (PictureSignConfig.enabled && !PictureSignType.isType(sign, PictureSignType.NONE)) cir.setReturnValue(true); + private static void shouldRender(BlockPos pos, int signColor, CallbackInfoReturnable cir) { + if (PictureSignConfig.enabled && client.world != null && !PictureSignType.hasNoPicture((SignBlockEntity) client.world.getBlockEntity(pos))) cir.setReturnValue(true); } @Unique @Override @@ -37,6 +41,6 @@ public abstract class MixinSignBlockEntityRenderer implements BlockEntityRendere @Unique @Override public boolean rendersOutsideBoundingBox(SignBlockEntity sign) { - return PictureSignConfig.enabled && !PictureSignType.isType(sign, PictureSignType.NONE); + return PictureSignConfig.enabled && !PictureSignType.hasNoPicture(sign); } } diff --git a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignEditScreen.java b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignEditScreen.java index fe3619e..d94824f 100644 --- a/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignEditScreen.java +++ b/src/main/java/eu/midnightdust/picturesign/mixin/MixinSignEditScreen.java @@ -6,7 +6,7 @@ import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.screen.PictureSignHelperScreen; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.SignEditScreen; +import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Final; @@ -20,14 +20,17 @@ import java.util.Objects; import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID; -@Mixin(SignEditScreen.class) +@Mixin(AbstractSignEditScreen.class) public abstract class MixinSignEditScreen extends Screen { private static final Identifier PICTURESIGN_ICON_TEXTURE = new Identifier(MOD_ID,"textures/gui/picturesign_button.png"); private static final Identifier CLIPBOARD_ICON_TEXTURE = new Identifier(MOD_ID,"textures/gui/clipboard_button.png"); private static final Identifier TRASHBIN_ICON_TEXTURE = new Identifier(MOD_ID,"textures/gui/trashbin_button.png"); - @Shadow @Final private SignBlockEntity sign; + @Shadow @Final private SignBlockEntity blockEntity; - @Shadow @Final private String[] text; + @Shadow @Final private String[] messages; + + @Shadow @Final private boolean front; + private static boolean switchScreen = false; protected MixinSignEditScreen(Text title) { super(title); @@ -38,21 +41,32 @@ public abstract class MixinSignEditScreen extends Screen { if (PictureSignClient.clipboard != null && PictureSignClient.clipboard[0] != null) this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 84, this.height - 40, 20, 20, 0, 0, 20, CLIPBOARD_ICON_TEXTURE, 32, 64, (buttonWidget) -> { for (int i = 0; i < 4; i++) { - text[i] = PictureSignClient.clipboard[i]; - sign.setTextOnRow(i, Text.of(text[i])); + messages[i] = PictureSignClient.clipboard[i]; + int finalI = i; + blockEntity.changeText(changer -> changer.withMessage(finalI, Text.of(messages[finalI])), front); } }, Text.empty())); if (PictureSignConfig.helperUi) this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 62, this.height - 40, 20, 20, 0, 0, 20, TRASHBIN_ICON_TEXTURE, 32, 64, (buttonWidget) -> { for (int i = 0; i < 4; i++) { - text[i] = ""; - sign.setTextOnRow(i, Text.empty()); + messages[i] = ""; + int finalI = i; + blockEntity.changeText(changer -> changer.withMessage(finalI, Text.empty()), front); } }, Text.empty())); if (PictureSignConfig.helperUi) this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 40, this.height - 40, 20, 20, 0, 0, 20, PICTURESIGN_ICON_TEXTURE, 32, 64, (buttonWidget) -> { - sign.setEditable(true); - Objects.requireNonNull(client).setScreen(new PictureSignHelperScreen(this.sign,false)); + switchScreen = true; + Objects.requireNonNull(client).setScreen(new PictureSignHelperScreen(this.blockEntity, front, false)); }, Text.empty())); } + @Inject(at = @At("HEAD"), method = "removed", cancellable = true) + private void picturesign$removed(CallbackInfo ci) { + if (switchScreen) { + switchScreen = false; + ci.cancel(); + } + } } + + diff --git a/src/main/java/eu/midnightdust/picturesign/render/PictureSignRenderer.java b/src/main/java/eu/midnightdust/picturesign/render/PictureSignRenderer.java index ca461af..73a9c2d 100755 --- a/src/main/java/eu/midnightdust/picturesign/render/PictureSignRenderer.java +++ b/src/main/java/eu/midnightdust/picturesign/render/PictureSignRenderer.java @@ -18,6 +18,7 @@ import net.minecraft.state.property.Properties; import net.minecraft.util.Identifier; import net.minecraft.util.math.*; import net.minecraft.world.World; +import org.joml.*; import java.net.MalformedURLException; @@ -25,9 +26,9 @@ import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID; public class PictureSignRenderer { private boolean isSafeUrl; - - public void render(SignBlockEntity signBlockEntity, MatrixStack matrixStack, int light, int overlay) { - String url = PictureURLUtils.getLink(signBlockEntity); + private boolean hasRotation = false; + public void render(SignBlockEntity signBlockEntity, MatrixStack matrixStack, int light, int overlay, boolean front) { + String url = PictureURLUtils.getLink(signBlockEntity, front); PictureInfo info = null; if (!url.contains("://")) { url = "https://" + url; @@ -40,19 +41,25 @@ public class PictureSignRenderer { if (!url.contains("://")) { url = "https://" + url; } - if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE) && !url.contains(".png") && !url.contains(".jpg") && !url.contains(".jpeg")) return; + if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE, front) && !url.contains(".png") && !url.contains(".jpg") && !url.contains(".jpeg")) return; if (PictureSignConfig.safeMode) { isSafeUrl = false; String finalUrl = url; PictureSignConfig.safeProviders.forEach(safe -> { if (!isSafeUrl) isSafeUrl = finalUrl.startsWith(safe); }); - if (!isSafeUrl) return; + if (!isSafeUrl && !url.startsWith("https://youtu.be/") && !url.startsWith("https://youtube.com/") && !url.startsWith("https://www.youtube.com/")) return; + } + if ((!PictureSignConfig.enableVideoSigns || !PlatformFunctions.isModLoaded("videolib")) && !PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE, front)) return; + if (url.startsWith("https://youtube.com/") || url.startsWith("https://www.youtube.com/watch?v=") || url.startsWith("https://youtu.be/")) { + url = url.replace("https://www.", "https://"); + url = url.replace("youtube.com/watch?v=", PictureSignConfig.invidiousInstance.replace("https://", "").replace("/", "")+"/latest_version?id="); + url = url.replace("youtu.be/", PictureSignConfig.invidiousInstance.replace("https://", "").replace("/", "")+"/latest_version?id="); } - if ((!PictureSignConfig.enableVideoSigns || !PlatformFunctions.isModLoaded("videolib")) && !PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE)) return; World world = signBlockEntity.getWorld(); BlockPos pos = signBlockEntity.getPos(); - Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()); + String videoSuffix = front ? "_f" : "_b"; + Identifier videoId = new Identifier(MOD_ID, pos.getX() + "_" + pos.getY() + "_" + pos.getZ()+videoSuffix); if (world != null && ((world.getBlockState(pos.down()).getBlock().equals(Blocks.REDSTONE_TORCH) || world.getBlockState(pos.down()).getBlock().equals(Blocks.REDSTONE_WALL_TORCH)) && world.getBlockState(pos.down()).get(Properties.LIT).equals(false) || (world.getBlockState(pos.up()).getBlock().equals(Blocks.REDSTONE_TORCH) || world.getBlockState(pos.up()).getBlock().equals(Blocks.REDSTONE_WALL_TORCH)) @@ -63,7 +70,7 @@ public class PictureSignRenderer { return; } - String lastLine = signBlockEntity.getTextOnRow(3, false).getString(); + String lastLine = signBlockEntity.getText(front).getMessage(3, false).getString(); if (!lastLine.matches("(.*\\d:.*\\d:.*\\d:.*\\d:.*\\d)")) return; @@ -82,16 +89,32 @@ public class PictureSignRenderer { } catch (NumberFormatException ignored) {} + String thirdLine = signBlockEntity.getText(front).getMessage(2, false).getString(); + hasRotation = thirdLine.matches("(.*\\d:.*\\d:.*\\d)"); + float xRot = 0; + float yRot = 0; + float zRot = 0; + + if (hasRotation) { + String[] rotation = thirdLine.split(":"); + try { + xRot = Float.parseFloat(rotation[0]); + yRot = Float.parseFloat(rotation[1]); + zRot = Float.parseFloat(rotation[2]); + } catch (NumberFormatException ignored) { + } + } + // Download the picture data PictureDownloader.PictureData data = null; - if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE)) { + if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE, front)) { data = PictureDownloader.getInstance().getPicture(url); if (data == null || data.identifier == null) return; } - else if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO) || PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO)) { + else if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO, front) || PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO, front)) { VideoHandler.videoPlayers.add(videoId); try { - if (PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO) && !VideoHandler.hasMedia(videoId)) { + if (PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO, front) && !VideoHandler.hasMedia(videoId)) { VideoHandler.play(videoId, url); VideoHandler.setRepeat(videoId, true); } @@ -108,12 +131,12 @@ public class PictureSignRenderer { } else return; - if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO)) VideoHandler.playedOnce.add(videoId); + if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO, front)) VideoHandler.playedOnce.add(videoId); float xOffset = 0.0F; float zOffset = 0.0F; - Quaternion yRotation = Vec3f.POSITIVE_Y.getDegreesQuaternion(0F); + float yRotation = 0; if (signBlockEntity.getCachedState().contains(Properties.HORIZONTAL_FACING)) { Direction direction = signBlockEntity.getCachedState().get(Properties.HORIZONTAL_FACING); @@ -121,48 +144,48 @@ public class PictureSignRenderer { case NORTH -> { zOffset = 1.01F; xOffset = 1.0F; - yRotation = Vec3f.POSITIVE_Y.getDegreesQuaternion(180.0F); + yRotation = 180; } case SOUTH -> zOffset = 0.010F; case EAST -> { zOffset = 1.01F; - yRotation = Vec3f.POSITIVE_Y.getDegreesQuaternion(90.0F); + yRotation = 90; } case WEST -> { - yRotation = Vec3f.POSITIVE_Y.getDegreesQuaternion(-90.0F); + yRotation = -90; xOffset = 1.01F; } } } else if (signBlockEntity.getCachedState().contains(Properties.ROTATION)) { - yRotation = Vec3f.POSITIVE_Y.getDegreesQuaternion(signBlockEntity.getCachedState().get(Properties.ROTATION) * -22.5f); + yRotation = signBlockEntity.getCachedState().get(Properties.ROTATION) * -22.5f; } else return; + if (!front) yRotation -= 180f; Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuffer(); - int l; + int l = PictureSignConfig.fullBrightPicture ? 15728880 : light; if (FabricLoader.getInstance().isModLoaded("iris") && IrisApi.getInstance().isShaderPackInUse()) { - RenderSystem.setShader(GameRenderer::getRenderTypeCutoutShader); - l = 15728880; - } - else { - RenderSystem.setShader(GameRenderer::getPositionColorTexLightmapShader); - l = light; + RenderSystem.setShader(PictureSignConfig.pictureShader.program); } + else RenderSystem.setShader(GameRenderer::getPositionColorTexLightmapProgram); + Identifier texture; - if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE)) { + if (PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE, front)) { assert data != null; texture = data.identifier; } - else if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO) || PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO)) + else if (PictureSignType.isType(signBlockEntity, PictureSignType.VIDEO, front) || PictureSignType.isType(signBlockEntity, PictureSignType.LOOPED_VIDEO, front)) texture = VideoHandler.getTexture(videoId); else return; TextureManager textureManager = MinecraftClient.getInstance().getTextureManager(); - if (textureManager.getTexture(texture) == null || (textureManager.getTexture(texture) instanceof NativeImageBackedTexture nativeTexture && nativeTexture.getImage() == null)) { + if (textureManager.getTexture(texture) == null || (textureManager.getTexture(texture) instanceof NativeImageBackedTexture nativeTexture && nativeTexture.getImage() == null) || + (!PictureSignType.isType(signBlockEntity, PictureSignType.PICTURE, front) && VideoHandler.getFramerate(videoId) < 1)) { if (PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.TRANSPARENT)) return; - texture = PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.BLACK) ? (new Identifier(MOD_ID, "textures/black.png")) : (TextureManager.MISSING_IDENTIFIER); + texture = PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.BLACK) ? + (new Identifier(MOD_ID, "textures/black.png")) : (TextureManager.MISSING_IDENTIFIER); } RenderSystem.setShaderTexture(0, texture); @@ -173,7 +196,12 @@ public class PictureSignRenderer { matrixStack.push(); matrixStack.translate(xOffset + x, y, zOffset + z); - matrixStack.multiply(yRotation); + matrixStack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yRotation + yRot)); + matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(xRot)); + matrixStack.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(zRot)); + //System.out.println(hasRotation +" "+ xRot + " " + yRot + " " + zRot); + + //matrixStack.multiply(new Quaternionf(new AxisAngle4d(Math.toRadians(yRotation + yRot), 0, 1, 0))); Matrix4f matrix4f = matrixStack.peek().getPositionMatrix(); buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_LIGHT); diff --git a/src/main/java/eu/midnightdust/picturesign/screen/PictureSignHelperScreen.java b/src/main/java/eu/midnightdust/picturesign/screen/PictureSignHelperScreen.java index ff1bfde..d92c6ce 100644 --- a/src/main/java/eu/midnightdust/picturesign/screen/PictureSignHelperScreen.java +++ b/src/main/java/eu/midnightdust/picturesign/screen/PictureSignHelperScreen.java @@ -3,13 +3,17 @@ package eu.midnightdust.picturesign.screen; import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget; import eu.midnightdust.picturesign.PictureSignClient; import eu.midnightdust.picturesign.config.PictureSignConfig; +import eu.midnightdust.picturesign.util.PictureSignType; import eu.midnightdust.picturesign.util.PictureURLUtils; -import net.minecraft.block.BlockState; -import net.minecraft.block.SignBlock; +import net.minecraft.block.*; import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HangingSignEditScreen; import net.minecraft.client.gui.screen.ingame.SignEditScreen; import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.render.*; @@ -18,11 +22,15 @@ import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket; import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import net.minecraft.util.math.Matrix4f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import java.util.stream.IntStream; import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID; @@ -33,34 +41,43 @@ public class PictureSignHelperScreen extends Screen { private static final Identifier TRASHBIN_ICON_TEXTURE = new Identifier(MOD_ID,"textures/gui/trashbin_button.png"); private final SignBlockEntity sign; private SignBlockEntityRenderer.SignModel model; - private String[] text; + protected String[] text; + private final boolean front; + private final boolean isHanging; + protected final WoodType signType; + private static boolean switchScreen = false; + private PictureSignType pictureSignType = PictureSignType.PICTURE; - public PictureSignHelperScreen(SignBlockEntity sign, boolean filtered) { - super(Text.translatable("sign.edit")); + public PictureSignHelperScreen(SignBlockEntity sign, boolean front, boolean filtered) { + super((sign.getCachedState().getBlock() instanceof HangingSignBlock || sign.getCachedState().getBlock() instanceof WallHangingSignBlock) ? Text.translatable("hanging_sign.edit") : Text.translatable("sign.edit")); this.text = IntStream.range(0, 4).mapToObj((row) -> - sign.getTextOnRow(row, filtered)).map(Text::getString).toArray(String[]::new); + sign.getText(front).getMessage(row, filtered)).map(Text::getString).toArray(String[]::new); this.sign = sign; + this.signType = AbstractSignBlock.getWoodType(sign.getCachedState().getBlock()); + this.isHanging = sign.getCachedState().getBlock() instanceof HangingSignBlock || sign.getCachedState().getBlock() instanceof WallHangingSignBlock; + + this.front = front; } protected void init() { super.init(); if (this.client == null) return; - sign.setEditable(false); text = IntStream.range(0, 4).mapToObj((row) -> - sign.getTextOnRow(row, false)).map(Text::getString).toArray(String[]::new); + sign.getText(front).getMessage(row, false)).map(Text::getString).toArray(String[]::new); if (!text[3].matches("(.*\\d:.*\\d:.*\\d:.*\\d:.*\\d)")) text[3] = "1:1:0:0:0"; if (!text[0].startsWith("!PS:") && !text[0].startsWith("!VS:") && !text[0].startsWith("!LS:")) text[0] = "!PS:"+text[0]; - for (int i = 0; i < 3; i++) { - sign.setTextOnRow(i, Text.of(text[i])); + if (text[2].isBlank() && PictureSignConfig.exceedVanillaLineLength) text[2] = "0:0:0"; + for (int i = 0; i < 4; i++) { + int finalI = i; + sign.changeText(changer -> changer.withMessage(finalI, Text.of(text[finalI])), front); } - this.addDrawableChild(new ButtonWidget(this.width / 2 - 100, this.height / 4 + 120, 200, 20, ScreenTexts.DONE, (button) -> { - this.finishEditing(); - })); + this.addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, (button) -> this.finishEditing()).dimensions(this.width / 2 - 100, this.height / 4 + 120, 200, 20).build()); if (PictureSignClient.clipboard != null && PictureSignClient.clipboard[0] != null) this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 84, this.height - 40, 20, 20, 0, 0, 20, CLIPBOARD_ICON_TEXTURE, 32, 64, (buttonWidget) -> { for (int i = 0; i < 4; i++) { text[i] = PictureSignClient.clipboard[i]; - sign.setTextOnRow(i, Text.of(text[i])); + int finalI = i; + sign.changeText(changer -> changer.withMessage(finalI, Text.of(text[finalI])), front); } assert client != null; client.setScreen(this); @@ -69,178 +86,172 @@ public class PictureSignHelperScreen extends Screen { this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 62, this.height - 40, 20, 20, 0, 0, 20, TRASHBIN_ICON_TEXTURE, 32, 64, (buttonWidget) -> { for (int i = 0; i < 4; i++) { text[i] = ""; - sign.setTextOnRow(i, Text.empty()); + int finalI = i; + sign.changeText(changer -> changer.withMessage(finalI, Text.empty()), front); } assert client != null; client.setScreen(this); }, Text.of(""))); this.addDrawableChild(new TexturedOverlayButtonWidget(this.width - 40, this.height - 40, 20, 20, 0, 0, 20, TEXTSIGN_ICON_TEXTURE, 32, 64, (buttonWidget) -> { - sign.setEditable(true); - Objects.requireNonNull(client).setScreen(new SignEditScreen(this.sign,false)); + switchScreen = true; + Objects.requireNonNull(client).setScreen(isHanging ? new HangingSignEditScreen(this.sign, false, front) : new SignEditScreen(this.sign, front, false)); }, Text.of(""))); - this.addDrawableChild(new ButtonWidget(this.width / 2,this.height / 5 + 70,40,20, Text.of(text[0].startsWith("!PS:") ? "Image" : (text[0].startsWith("!VS:") ? "Video" : "Loop")), (buttonWidget) -> { + if (text[0].startsWith("!VS:")) pictureSignType = PictureSignType.VIDEO; + if (text[0].startsWith("!LS:")) pictureSignType = PictureSignType.LOOPED_VIDEO; + this.addDrawableChild(ButtonWidget.builder(Text.of(text[0].startsWith("!PS:") ? "Image" : (text[0].startsWith("!VS:") ? "Video" : "Loop")), (buttonWidget) -> { if (text[0].startsWith("!PS:")) text[0] = "!VS:" + text[0].replace("!PS:","").replace("!VS:", "").replace("!LS:", ""); else if (text[0].startsWith("!VS:")) text[0] = "!LS:" + text[0].replace("!PS:","").replace("!VS:", "").replace("!LS:", ""); else if (text[0].startsWith("!LS:")) text[0] = "!PS:" + text[0].replace("!PS:","").replace("!VS:", "").replace("!LS:", ""); else text[0] = "!PS:" + text[0].replace("!PS:","").replace("!VS:", "").replace("!LS:", ""); buttonWidget.setMessage(Text.of(text[0].startsWith("!PS:") ? "Image" : (text[0].startsWith("!VS:") ? "Video" : "Loop"))); + pictureSignType = text[0].startsWith("!PS:") ? PictureSignType.PICTURE : (text[0].startsWith("!VS:") ? PictureSignType.VIDEO : PictureSignType.LOOPED_VIDEO); - sign.setTextOnRow(0, Text.of(text[0])); - })); + sign.changeText(changer -> changer.withMessage(0, Text.of(text[0])), front); + }).dimensions(this.width / 2,this.height / 5 + 70,40,20).build()); TextFieldWidget linkWidget = new TextFieldWidget(textRenderer,this.width / 2 - 175,this.height / 5 + 13,215,40, Text.of("url")); linkWidget.setMaxLength(900); - linkWidget.setText(PictureURLUtils.getLink(sign)); + linkWidget.setText(PictureURLUtils.getLink(sign, front)); linkWidget.setChangedListener(s -> { String prefix = ""; if (text[0].startsWith("!PS:")) prefix = "!PS:"; else if (text[0].startsWith("!VS:")) prefix = "!VS:"; else if (text[0].startsWith("!LS:")) prefix = "!LS:"; String[] lines = breakLink(prefix, PictureURLUtils.shortenLink(s)); - for (int i = 0; i < 3; i++) { + for (int i = 0; i < (PictureSignConfig.exceedVanillaLineLength ? 2 : 3); i++) { text[i] = lines[i]; - sign.setTextOnRow(i, Text.of(text[i])); + int finalI = i; + sign.changeText(changer -> changer.withMessage(finalI, Text.of(text[finalI])), front); } }); this.addDrawableChild(linkWidget); String[] initialDimensions = text[3].split(":"); TextFieldWidget widthWidget = new TextFieldWidget(textRenderer,this.width / 2 - 175,this.height / 5 + 70,30,20, Text.of("width")); - widthWidget.setText(initialDimensions[0]); - widthWidget.setChangedListener(s -> { - String[] dimensions = new String[5]; - for (int i = 0; i < dimensions.length; ++i){ - if (text[3].split(":").length > i) - dimensions[i] = text[3].split(":")[i]; - } - dimensions[0] = s; - StringBuilder mergedDimensions = new StringBuilder(); - for (int i = 0; i < 5; ++i) { - if (dimensions[i] == null) dimensions[i] = ""; - mergedDimensions.append(dimensions[i]); - if (i < 4)mergedDimensions.append(":"); - } - text[3] = String.valueOf(mergedDimensions); - sign.setTextOnRow(3, Text.of(text[3])); - }); - this.addDrawableChild(widthWidget); TextFieldWidget heightWidget = new TextFieldWidget(textRenderer,this.width / 2 - 140,this.height / 5 + 70,30,20, Text.of("height")); - heightWidget.setText(initialDimensions[1]); - heightWidget.setChangedListener(s -> { - String[] dimensions = new String[5]; - for (int i = 0; i < dimensions.length; ++i){ - if (text[3].split(":").length > i) - dimensions[i] = text[3].split(":")[i]; - } - dimensions[1] = s; - StringBuilder mergedDimensions = new StringBuilder(); - for (int i = 0; i < 5; ++i) { - if (dimensions[i] == null) dimensions[i] = ""; - mergedDimensions.append(dimensions[i]); - if (i < 4)mergedDimensions.append(":"); - } - text[3] = String.valueOf(mergedDimensions); - sign.setTextOnRow(3, Text.of(text[3])); - }); - this.addDrawableChild(heightWidget); TextFieldWidget posXWidget = new TextFieldWidget(textRenderer,this.width / 2 - 105,this.height / 5 + 70,30,20, Text.of("posX")); - posXWidget.setText(initialDimensions[2]); - posXWidget.setChangedListener(s -> { - String[] dimensions = new String[5]; - for (int i = 0; i < dimensions.length; ++i){ - if (text[3].split(":").length > i) - dimensions[i] = text[3].split(":")[i]; - } - dimensions[2] = s; - StringBuilder mergedDimensions = new StringBuilder(); - for (int i = 0; i < 5; ++i) { - if (dimensions[i] == null) dimensions[i] = ""; - mergedDimensions.append(dimensions[i]); - if (i < 4)mergedDimensions.append(":"); - } - text[3] = String.valueOf(mergedDimensions); - sign.setTextOnRow(3, Text.of(text[3])); - }); - this.addDrawableChild(posXWidget); TextFieldWidget posYWidget = new TextFieldWidget(textRenderer,this.width / 2 - 70,this.height / 5 + 70,30,20, Text.of("posY")); - posYWidget.setText(initialDimensions[3]); - posYWidget.setChangedListener(s -> { - String[] dimensions = new String[5]; - for (int i = 0; i < dimensions.length; ++i){ - if (text[3].split(":").length > i) - dimensions[i] = text[3].split(":")[i]; - } - dimensions[3] = s; - StringBuilder mergedDimensions = new StringBuilder(); - for (int i = 0; i < 5; ++i) { - if (dimensions[i] == null) dimensions[i] = ""; - mergedDimensions.append(dimensions[i]); - if (i < 4)mergedDimensions.append(":"); - } - text[3] = String.valueOf(mergedDimensions); - sign.setTextOnRow(3, Text.of(text[3])); - }); - this.addDrawableChild(posYWidget); TextFieldWidget posZWidget = new TextFieldWidget(textRenderer,this.width / 2 - 35,this.height / 5 + 70,30,20, Text.of("posZ")); + widthWidget.setText(initialDimensions[0]); + heightWidget.setText(initialDimensions[1]); + posXWidget.setText(initialDimensions[2]); + posYWidget.setText(initialDimensions[3]); posZWidget.setText(initialDimensions[4]); - posZWidget.setChangedListener(s -> { - String[] dimensions = new String[5]; - for (int i = 0; i < dimensions.length; ++i){ - if (text[3].split(":").length > i) - dimensions[i] = text[3].split(":")[i]; - } - dimensions[4] = s; - StringBuilder mergedDimensions = new StringBuilder(); - for (int i = 0; i < 5; ++i) { - if (dimensions[i] == null) dimensions[i] = ""; - mergedDimensions.append(dimensions[i]); - if (i < 4)mergedDimensions.append(":"); - } - text[3] = String.valueOf(mergedDimensions); - sign.setTextOnRow(3, Text.of(text[3])); - }); + widthWidget.setChangedListener(s -> applyPosition(s, 0)); + heightWidget.setChangedListener(s -> applyPosition(s, 1)); + posXWidget.setChangedListener(s -> applyPosition(s, 2)); + posYWidget.setChangedListener(s -> applyPosition(s, 3)); + posZWidget.setChangedListener(s -> applyPosition(s, 4)); + this.addDrawableChild(widthWidget); + this.addDrawableChild(heightWidget); + this.addDrawableChild(posXWidget); + this.addDrawableChild(posYWidget); this.addDrawableChild(posZWidget); - this.model = SignBlockEntityRenderer.createSignModel(this.client.getEntityModelLoader(), SignBlockEntityRenderer.getSignType(sign.getCachedState().getBlock())); + if (text[2].matches("(.*\\d:.*\\d:.*\\d)")) addRotationWidgets(); + this.model = SignBlockEntityRenderer.createSignModel(this.client.getEntityModelLoader(), AbstractSignBlock.getWoodType(sign.getCachedState().getBlock())); + } + public void applyPosition(String position, int index) { + String[] dimensions = new String[5]; + for (int i = 0; i < dimensions.length; ++i){ + if (text[3].split(":").length > i) + dimensions[i] = text[3].split(":")[i]; + } + dimensions[index] = position; + StringBuilder mergedDimensions = new StringBuilder(); + for (int i = 0; i < 5; ++i) { + if (dimensions[i] == null) dimensions[i] = ""; + mergedDimensions.append(dimensions[i]); + if (i < 4)mergedDimensions.append(":"); + } + text[3] = String.valueOf(mergedDimensions); + sign.changeText(changer -> changer.withMessage(3, Text.of(text[3])), front); + } + public void addRotationWidgets() { + String[] initialRotation = text[2].split(":"); + RotationSliderWidget rotXWidget = new RotationSliderWidget(this.width / 2 - 176,this.height / 5 + 100,70,20, Integer.parseInt(initialRotation[0])); + RotationSliderWidget rotYWidget = new RotationSliderWidget(this.width / 2 - 103,this.height / 5 + 100,70,20, Integer.parseInt(initialRotation[1])); + RotationSliderWidget rotZWidget = new RotationSliderWidget(this.width / 2 - 30,this.height / 5 + 100,70,20, Integer.parseInt(initialRotation[2])); + rotXWidget.setChangedListener(s -> applyRotation(s, 0)); + rotYWidget.setChangedListener(s -> applyRotation(s, 1)); + rotZWidget.setChangedListener(s -> applyRotation(s, 2)); + this.addDrawableChild(rotXWidget); + this.addDrawableChild(rotYWidget); + this.addDrawableChild(rotZWidget); + } + public void applyRotation(int rotation, int index) { + String[] dimensions = new String[3]; + for (int i = 0; i < dimensions.length; ++i){ + if (text[2].split(":").length > i) + dimensions[i] = text[2].split(":")[i]; + } + dimensions[index] = String.valueOf(rotation); + StringBuilder mergedDimensions = new StringBuilder(); + for (int i = 0; i < 3; ++i) { + if (dimensions[i] == null) dimensions[i] = ""; + mergedDimensions.append(dimensions[i]); + if (i < 2)mergedDimensions.append(":"); + } + text[2] = String.valueOf(mergedDimensions); + sign.changeText(changer -> changer.withMessage(2, Text.of(text[2])), front); + } + public static class RotationSliderWidget extends SliderWidget { + private Consumer changedListener; + + public RotationSliderWidget(int x, int y, int width, int height, int rot) { + super(x, y, width, height, Text.of(String.valueOf(rot)), rot / (360d)); + } + + protected void updateMessage() { + this.setMessage(Text.of(String.valueOf(getValue()))); + } + + @Override + protected void applyValue() { + changedListener.accept(getValue()); + } + + protected int getValue() { + return Double.valueOf(this.value * (360)).intValue(); + } + public void setChangedListener(Consumer changedListener) { + this.changedListener = changedListener; + } } public void removed() { - if (this.client == null) return; + if (this.client == null || switchScreen) return; ClientPlayNetworkHandler clientPlayNetworkHandler = this.client.getNetworkHandler(); for (int i = 0; i < 4; i++) { - sign.setTextOnRow(i, Text.of(text[i])); + int finalI = i; + sign.changeText(changer -> changer.withMessage(finalI, Text.of(text[finalI])), front); } if (clientPlayNetworkHandler != null) { - clientPlayNetworkHandler.sendPacket(new UpdateSignC2SPacket(this.sign.getPos(), this.text[0], this.text[1], this.text[2], this.text[3])); + clientPlayNetworkHandler.sendPacket(new UpdateSignC2SPacket(this.sign.getPos(), front, this.text[0], this.text[1], this.text[2], this.text[3])); } } + private String[] breakLink(String prefix, String link) { Text linkText = Text.of(prefix+link); String[] brokenLink = new String[3]; - Text line0Text = linkText; - int line0width = line0Text.getString().length(); - assert this.client != null; - while (this.client.textRenderer.getWidth(line0Text) >= 90) { - --line0width; - line0Text = Text.of(line0Text.getString().substring(0,line0width)); + assert client != null; + List text = client.textRenderer.wrapLines(linkText, 90); + for (int i = 0; i < text.size(); i++) { + String textLine = orderedToString(text.get(i)); + if (i < (PictureSignConfig.exceedVanillaLineLength ? 2 : 3)) + brokenLink[i] = textLine; + else if (PictureSignConfig.exceedVanillaLineLength) brokenLink[1] += textLine; } - brokenLink[0] = line0Text.getString(); - Text line1Text = Text.of(linkText.getString().substring(line0width)); - int line1width = line1Text.getString().length(); - assert this.client != null; - while (this.client.textRenderer.getWidth(line1Text) >= 90) { - --line1width; - line1Text = Text.of(line1Text.getString().substring(0,line1width)); - } - brokenLink[1] = line1Text.getString(); - Text line2Text = Text.of(linkText.getString().substring(line0width + line1width)); - int line2width = line2Text.getString().length(); - assert this.client != null; - if (!PictureSignConfig.exceedVanillaLineLength) - while (this.client.textRenderer.getWidth(line2Text) >= 90) { - --line2width; - line2Text = Text.of(line2Text.getString().substring(0,line2width)); - } - brokenLink[2] = line2Text.getString(); return brokenLink; } + private String orderedToString(OrderedText ordered) { + StringBuilder string = new StringBuilder(); + ordered.accept((i, style, codePoint) -> { + string.append(Character.toString(codePoint)); + return true; + }); return string.toString(); + } + @Override + public boolean shouldPause() { + return false; + } public void tick() { super.tick(); if (!this.sign.getType().supports(this.sign.getCachedState())) { @@ -252,40 +263,40 @@ public class PictureSignHelperScreen extends Screen { assert this.client != null; this.client.setScreen(null); } - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (this.client == null) return; DiffuseLighting.disableGuiDepthLighting(); - this.renderBackground(matrices); - drawTextWithShadow(matrices,textRenderer, Text.of("Link" + (PictureSignConfig.safeMode ? " (imgur.com/imgbb.com/iili.io/pictshare.net)" : "")),this.width / 2 - 175, this.height / 5 + 3, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("Width"),this.width / 2 - 175, this.height / 5 + 60, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("Height"),this.width / 2 - 140, this.height / 5 + 60, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("PosX"),this.width / 2 - 105, this.height / 5 + 60, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("PosY"),this.width / 2 - 70, this.height / 5 + 60, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("PosZ"),this.width / 2 - 35, this.height / 5 + 60, -8816268); - drawTextWithShadow(matrices,textRenderer, Text.of("Mode"),this.width / 2, this.height / 5 + 60, -8816268); - drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 40, 16777215); - matrices.push(); - matrices.translate(this.width / 2f + 100, this.height / 5f - 60, 50.0); - matrices.scale(93.75F, -93.75F, 93.75F); - matrices.translate(0.0, -1.3125, 0.0); - BlockState blockState = this.sign.getCachedState(); - boolean bl = blockState.getBlock() instanceof SignBlock; - if (!bl) { - matrices.translate(0.0, -0.3125, 0.0); + this.renderBackground(context); + context.drawTextWithShadow(textRenderer, Text.of("Link" + + (PictureSignConfig.safeMode ? (pictureSignType.equals(PictureSignType.PICTURE) ? " (imgur.com/imgbb.com/iili.io/pictshare.net)" : " (youtube.com/youtu.be/vimeo.com)") : "")), + this.width / 2 - 175, this.height / 5 + 3, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("Width"),this.width / 2 - 175, this.height / 5 + 60, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("Height"),this.width / 2 - 140, this.height / 5 + 60, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("PosX"),this.width / 2 - 105, this.height / 5 + 60, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("PosY"),this.width / 2 - 70, this.height / 5 + 60, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("PosZ"),this.width / 2 - 35, this.height / 5 + 60, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("Mode"),this.width / 2, this.height / 5 + 60, -8816268); + if (text[2].matches("(.*\\d:.*\\d:.*\\d)")) { + context.drawTextWithShadow(textRenderer, Text.of("RotX"),this.width / 2 - 175, this.height / 5 + 92, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("RotY"),this.width / 2 - 103, this.height / 5 + 92, -8816268); + context.drawTextWithShadow(textRenderer, Text.of("RotZ"),this.width / 2 - 30, this.height / 5 + 92, -8816268); } + context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 40, 16777215); + MatrixStack matrices = context.getMatrices(); matrices.push(); - matrices.scale(0.6666667F, -0.6666667F, -0.6666667F); VertexConsumerProvider.Immediate immediate = this.client.getBufferBuilders().getEntityVertexConsumers(); - SpriteIdentifier spriteIdentifier = TexturedRenderLayers.getSignTextureId(SignBlockEntityRenderer.getSignType(sign.getCachedState().getBlock())); - SignBlockEntityRenderer.SignModel var10002 = this.model; - Objects.requireNonNull(var10002); - VertexConsumer vertexConsumer = spriteIdentifier.getVertexConsumer(immediate, var10002::getLayer); - this.model.stick.visible = bl; - this.model.root.render(matrices, vertexConsumer, 15728880, OverlayTexture.DEFAULT_UV); + translateForRender(context, sign.getCachedState()); + renderSignBackground(context, sign.getCachedState()); + + int i = this.sign.getText(front).getColor().getSignColor(); matrices.pop(); - matrices.translate(0.0, 0.3333333432674408, 0.046666666865348816); - matrices.scale(0.010416667F, -0.010416667F, 0.010416667F); - int i = this.sign.getTextColor().getSignColor(); + matrices.push(); + + context.getMatrices().translate((float)this.width / 2.0F + 100, this.height / 5f + 47.5f, 400.0F); + if (sign.getCachedState().getBlock() instanceof SignBlock) context.getMatrices().translate(0,-15f,0); + else if (isHanging) context.getMatrices().translate(0,17f,0); + Vector3f vector3f = this.getTextScale(); + context.getMatrices().scale(vector3f.x(), vector3f.y(), vector3f.z()); Matrix4f matrix4f = matrices.peek().getPositionMatrix(); int m; @@ -298,7 +309,7 @@ public class PictureSignHelperScreen extends Screen { } float n = (float)(-this.client.textRenderer.getWidth(string) / 2); - this.client.textRenderer.draw(string, n, (float)(m * 10 - this.text.length * 5), i, false, matrix4f, immediate, false, 0, 15728880, false); + this.client.textRenderer.draw(string, n, (float)(m * 10 - this.text.length * 5), i, false, matrix4f, immediate, TextRenderer.TextLayerType.NORMAL, 0, 15728880, false); } } @@ -306,6 +317,53 @@ public class PictureSignHelperScreen extends Screen { matrices.pop(); DiffuseLighting.enableGuiDepthLighting(); - super.render(matrices, mouseX, mouseY, delta); + + super.render(context, mouseX, mouseY, delta); + } + protected void translateForRender(DrawContext context, BlockState state) { + MatrixStack matrices = context.getMatrices(); + if (isHanging) { + matrices.translate((float)this.width / 2.0F + 100, this.height / 5f + 50, 50.0F); + } + else { + matrices.push(); + matrices.translate(this.width / 2f + 100, this.height / 5f - 60, 50.0); + matrices.scale(93.75F, -93.75F, 93.75F); + matrices.translate(0.0, -1.3125, 0.0); + } + } + + protected void renderSignBackground(DrawContext context, BlockState state) { + if (!isHanging) { + VertexConsumerProvider.Immediate immediate = this.client.getBufferBuilders().getEntityVertexConsumers(); + MatrixStack matrices = context.getMatrices(); + + BlockState blockState = this.sign.getCachedState(); + boolean bl = blockState.getBlock() instanceof SignBlock; + if (!bl) { + matrices.translate(0.0, -0.15625, 0.0); + } + matrices.push(); + matrices.scale(0.6666667F, -0.6666667F, -0.6666667F); + + SpriteIdentifier spriteIdentifier = TexturedRenderLayers.getSignTextureId(AbstractSignBlock.getWoodType(sign.getCachedState().getBlock())); + SignBlockEntityRenderer.SignModel var10002 = this.model; + Objects.requireNonNull(var10002); + VertexConsumer vertexConsumer = spriteIdentifier.getVertexConsumer(immediate, var10002::getLayer); + this.model.stick.visible = bl; + this.model.root.render(matrices, vertexConsumer, 15728880, OverlayTexture.DEFAULT_UV); + matrices.pop(); + matrices.translate(0.0, 0.3333333432674408, 0.046666666865348816); + matrices.scale(0.010416667F, -0.010416667F, 0.010416667F); + } + else { + MatrixStack matrices = context.getMatrices(); + matrices.scale(4.5F, 4.5F, 1.0F); + context.drawTexture(new Identifier("textures/gui/hanging_signs/" + this.signType.name() + ".png"), -8, -8, 0.0F, 0.0F, 16, 16, 16, 16); + } + } + + protected Vector3f getTextScale() { + return isHanging ? new Vector3f(1.0F, 1.0F, 1.0F) : new Vector3f(0.9765628F, 0.9765628F, 0.9765628F); } } diff --git a/src/main/java/eu/midnightdust/picturesign/util/PictureSignType.java b/src/main/java/eu/midnightdust/picturesign/util/PictureSignType.java index b2287c4..776f702 100644 --- a/src/main/java/eu/midnightdust/picturesign/util/PictureSignType.java +++ b/src/main/java/eu/midnightdust/picturesign/util/PictureSignType.java @@ -4,14 +4,17 @@ import net.minecraft.block.entity.SignBlockEntity; public enum PictureSignType { NONE, PICTURE, VIDEO, LOOPED_VIDEO; - public static PictureSignType getType(SignBlockEntity signBlockEntity) { - String rowOne = signBlockEntity.getTextOnRow(0,false).getString(); + public static PictureSignType getType(SignBlockEntity signBlockEntity, boolean front) { + String rowOne = signBlockEntity.getText(front).getMessage(0,false).getString(); if (rowOne.startsWith("!PS:")) return PICTURE; if (rowOne.startsWith("!VS:")) return VIDEO; if (rowOne.startsWith("!LS:")) return LOOPED_VIDEO; else return NONE; } - public static boolean isType(SignBlockEntity signBlockEntity, PictureSignType type) { - return getType(signBlockEntity) == type; + public static boolean isType(SignBlockEntity signBlockEntity, PictureSignType type, boolean front) { + return getType(signBlockEntity, front) == type; + } + public static boolean hasNoPicture(SignBlockEntity signBlockEntity) { + return isType(signBlockEntity, NONE, true) && isType(signBlockEntity, NONE, false); } } diff --git a/src/main/java/eu/midnightdust/picturesign/util/PictureURLUtils.java b/src/main/java/eu/midnightdust/picturesign/util/PictureURLUtils.java index e076556..9d0f1ba 100644 --- a/src/main/java/eu/midnightdust/picturesign/util/PictureURLUtils.java +++ b/src/main/java/eu/midnightdust/picturesign/util/PictureURLUtils.java @@ -18,7 +18,6 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -@SuppressWarnings("UnstableApiUsage") public class PictureURLUtils { public static final Type STRING_TYPE = new TypeToken>(){}.getType(); public static final Map cachedJsonData = new HashMap<>(); @@ -60,15 +59,16 @@ public class PictureURLUtils { catch (MalformedURLException e) {PictureSignClient.LOGGER.warn("Malformed URL: " + e);} return result; } - public static String getLink(SignBlockEntity signBlockEntity) { - String text = signBlockEntity.getTextOnRow(0, false).getString() + - signBlockEntity.getTextOnRow(1, false).getString() + - signBlockEntity.getTextOnRow(2, false).getString(); + public static String getLink(SignBlockEntity signBlockEntity, boolean front) { + String text = signBlockEntity.getText(front).getMessage(0, false).getString() + + signBlockEntity.getText(front).getMessage(1, false).getString(); + if (!signBlockEntity.getText(front).getMessage(2, false).getString().matches("(.*\\d:.*\\d:.*\\d)")) text += signBlockEntity.getText(front).getMessage(2, false).getString(); String url = text.replaceAll("!PS:", "").replaceAll("!VS:", "").replaceAll("!LS:", "").replaceAll(" ",""); if (url.startsWith("ps:")) url = url.replace("ps:", "https://pictshare.net/"); if (url.startsWith("imgur:")) url = url.replace("imgur:", "https://i.imgur.com/"); if (url.startsWith("imgbb:")) url = url.replace("imgbb:", "https://i.ibb.co/"); if (url.startsWith("iili:")) url = url.replace("iili:", "https://iili.io/"); + if (url.startsWith("yt:")) url = url.replace("yt:", "https://youtu.be/"); return url; } public static String shortenLink(String url) { @@ -76,9 +76,13 @@ public class PictureURLUtils { if (url.contains("i.imgur.com/")) url = url.replace("i.imgur.com/", "imgur:"); if (url.contains("i.ibb.co/:")) url = url.replace("i.ibb.co/", "imgbb:"); if (url.contains("iili.io/")) url = url.replace("iili.io/", "iili:"); + if (url.contains("www.youtube.com/")) url = url.replace("www.youtube.com/", "yt:"); + if (url.contains("youtu.be/")) url = url.replace("youtu.be/", "yt:"); if (url.startsWith("https://")) { url = url.replace("https://", ""); } + if (url.contains("watch?v=")) url = url.replace("watch?v=", ""); + if (url.contains("&pp=")) url = url.split("&pp=")[0]; return url; } } diff --git a/src/main/java/eu/midnightdust/picturesign/util/VideoHandler.java b/src/main/java/eu/midnightdust/picturesign/util/VideoHandler.java index 8e6660a..6ea18e8 100644 --- a/src/main/java/eu/midnightdust/picturesign/util/VideoHandler.java +++ b/src/main/java/eu/midnightdust/picturesign/util/VideoHandler.java @@ -38,4 +38,7 @@ public class VideoHandler { public static Identifier getTexture(Identifier id) { return videoManager.getOrCreate(id).getTexture(); } + public static float getFramerate(Identifier id) { + return videoManager.getOrCreate(id).getCodecInterface().getFrameRate(); + } } diff --git a/src/main/resources/assets/picturesign/lang/de_de.json b/src/main/resources/assets/picturesign/lang/de_de.json index 5fdd0bf..67776c4 100755 --- a/src/main/resources/assets/picturesign/lang/de_de.json +++ b/src/main/resources/assets/picturesign/lang/de_de.json @@ -11,13 +11,22 @@ "picturesign.midnightconfig.signRenderDistance":"Schildsichtweite", "picturesign.midnightconfig.safeMode":"Sicherer Modus", "picturesign.midnightconfig.safeMode.tooltip":"Lädt nur Bilder von vertrauten Seiten", - "picturesign.midnightconfig.ebeWarning":"§cWenn du die Mod 'Enhanced Block Entities' benutzt, stelle sicher,", - "picturesign.midnightconfig.ebeWarning2":"§cdass du alles in Relation zu Schildern in der EBE Config deaktiviert hast!", + "picturesign.midnightconfig.ebeWarning":"§cWenn du die Mod 'Enhanced Block Entities' benutzt, stelle sicher, dass du alles in Relation zu Schildern in der EBE Config deaktiviert hast!", "picturesign.midnightconfig.safeProviders":"Sichere Anbieter", "picturesign.midnightconfig.missingImageMode":"Darstellung fehlender Texturen", "picturesign.midnightconfig.enum.MissingImageMode.BLACK":"Schwarz", "picturesign.midnightconfig.enum.MissingImageMode.MISSING_TEXTURE":"Schwarz & Lila", "picturesign.midnightconfig.enum.MissingImageMode.TRANSPARENT":"Transparent", "key.picturesign.copy_sign": "Text eines Schildes kopieren", - "key.picturesign.edit_sign":"Schild bearbeiten" + "key.picturesign.edit_sign":"Schild bearbeiten", + + "picturesign.midnightconfig.category.1general": "Generell", + "picturesign.midnightconfig.category.advanced": "Fortgeschritten", + "picturesign.midnightconfig.enableVideoSigns": "Aktiviere Videos", + "picturesign.midnightconfig.fullBrightPicture": "Höchste Helligkeit", + "picturesign.midnightconfig.fullBrightPicture.tooltip": "Sorgt dafür, dass Bilder immer vollkommen beleuchtet dargestellt werden", + "picturesign.midnightconfig.invidiousInstance": "Invidious-Instanz", + "picturesign.midnightconfig.invidiousInstance.tooltip": "Wähle die Invidious-Instanz aus, die zur Wiedergabe von YouTube-Videos verwendet wird. \nEine Liste dieser ist zu finden unter\ndocs.invidious.io/instances/", + "picturesign.midnightconfig.pictureShader": "Render-Programm", + "picturesign.midnightconfig.pictureShader.tooltip": "Wähle das Shader-Programm, mit dem die Bilder dargestellt werden, was nützlich ist, wenn diese mit Shaderpacks nicht richtig dargestellt werden" } \ No newline at end of file diff --git a/src/main/resources/assets/picturesign/lang/en_us.json b/src/main/resources/assets/picturesign/lang/en_us.json index 71fbc67..cb4ba90 100755 --- a/src/main/resources/assets/picturesign/lang/en_us.json +++ b/src/main/resources/assets/picturesign/lang/en_us.json @@ -1,10 +1,14 @@ { "picturesign.midnightconfig.title":"PictureSign Config", + "picturesign.midnightconfig.category.1general":"General", + "picturesign.midnightconfig.category.advanced":"Advanced", "picturesign.midnightconfig.enabled":"Enable Pictures", "picturesign.midnightconfig.enableVideoSigns":"Enable Videos", "picturesign.midnightconfig.translucency":"Enable Translucency", "picturesign.midnightconfig.translucency.tooltip":"Translucency doesn't work too great on block entities\n(and therefore signs)", + "picturesign.midnightconfig.fullBrightPicture":"Full-bright Pictures", + "picturesign.midnightconfig.fullBrightPicture.tooltip":"Makes pictures always appear fully lit", "picturesign.midnightconfig.helperUi":"Enable Helper UI", "picturesign.midnightconfig.exceedVanillaLineLength":"Exceed vanilla line length", "picturesign.midnightconfig.debug":"Debug mode", @@ -12,13 +16,21 @@ "picturesign.midnightconfig.signRenderDistance":"Sign render distance", "picturesign.midnightconfig.safeMode":"Safe mode", "picturesign.midnightconfig.safeMode.tooltip":"Only load images from trusted providers", - "picturesign.midnightconfig.ebeWarning":"§cIf you are using the mod 'Enhanced Block Entities'", - "picturesign.midnightconfig.ebeWarning2":"§cmake sure to disable anything sign-related in it's config!", + "picturesign.midnightconfig.ebeWarning":"§cIf you are using the mod 'Enhanced Block Entities' make sure to disable anything sign-related in it's config!", "picturesign.midnightconfig.safeProviders":"Safe providers", + "picturesign.midnightconfig.invidiousInstance":"Invidious Instance", + "picturesign.midnightconfig.invidiousInstance.tooltip":"Select the Invidious instance that is being used to play YouTube videos. \nYou can find a list of them at\ndocs.invidious.io/instances/", "picturesign.midnightconfig.missingImageMode":"Missing image mode", "picturesign.midnightconfig.enum.MissingImageMode.BLACK":"Black", "picturesign.midnightconfig.enum.MissingImageMode.MISSING_TEXTURE":"Black & Purple", "picturesign.midnightconfig.enum.MissingImageMode.TRANSPARENT":"Transparent", + "picturesign.midnightconfig.pictureShader":"Render Program", + "picturesign.midnightconfig.pictureShader.tooltip":"Select the shader program to draw pictures with when using shaderpacks where they appear black/buggy", + "picturesign.midnightconfig.enum.PictureShader.PosColTexLight":"PosColTexLight", + "picturesign.midnightconfig.enum.PictureShader.RenderTypeCutout":"RenderTypeCutout", + "picturesign.midnightconfig.enum.PictureShader.PosTex":"PosTex", + "picturesign.midnightconfig.enum.PictureShader.PosColTex":"PosColTex", + "picturesign.midnightconfig.enum.PictureShader.PosTexCol":"PosTexCol", "key.picturesign.copy_sign":"Copy Text from Sign", "key.picturesign.edit_sign":"Edit Sign", "key.categories.picturesign":"PictureSign" diff --git a/src/main/resources/picturesign.mixins.json b/src/main/resources/picturesign.mixins.json index 6e7680b..b599655 100755 --- a/src/main/resources/picturesign.mixins.json +++ b/src/main/resources/picturesign.mixins.json @@ -4,6 +4,7 @@ "compatibilityLevel": "JAVA_17", "client": [ "MixinSignBlockEntityRenderer", + "MixinHangingSignBlockEntityRenderer", "MixinSignEditScreen", "MixinSignBlockEntity" ],