Better error handling & translations

- There is now a detailed error message on the surface when a picture/GIF/video could not be loaded
- Made more strings translatable
This commit is contained in:
Martin Prokoph
2024-07-02 23:19:47 +02:00
parent dd33f55735
commit 8536139272
12 changed files with 215 additions and 119 deletions

View File

@@ -4,7 +4,6 @@ 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;
@@ -15,6 +14,9 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static eu.midnightdust.picturesign.util.PictureSignType.isCandidate;
import static eu.midnightdust.picturesign.util.PictureSignType.isNotOfType;
@Mixin(HangingSignBlockEntityRenderer.class)
public abstract class MixinHangingSignBlockEntityRenderer implements BlockEntityRenderer<SignBlockEntity> {
@Unique PictureSignRenderer psRenderer = new PictureSignRenderer();
@@ -22,8 +24,8 @@ public abstract class MixinHangingSignBlockEntityRenderer implements BlockEntity
@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.isNotOfType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, light, overlay, true);
if (PictureSignType.isNotOfType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, light, overlay, false);
if (isCandidate(sign, true) && isNotOfType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, true);
if (isCandidate(sign, false) && isNotOfType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, false);
}
}
@Unique

View File

@@ -4,7 +4,7 @@ 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.render.*;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer;
@@ -18,6 +18,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static eu.midnightdust.picturesign.PictureSignClient.client;
import static eu.midnightdust.picturesign.util.PictureSignType.isCandidate;
import static eu.midnightdust.picturesign.util.PictureSignType.isNotOfType;
import static eu.midnightdust.picturesign.util.PictureSignType.hasPicture;
@Mixin(SignBlockEntityRenderer.class)
public abstract class MixinSignBlockEntityRenderer implements BlockEntityRenderer<SignBlockEntity> {
@@ -31,13 +34,13 @@ public abstract class MixinSignBlockEntityRenderer implements BlockEntityRendere
@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 && psRenderer != null) {
if (PictureSignType.isNotOfType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, light, overlay, true);
if (PictureSignType.isNotOfType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, light, overlay, false);
if (isCandidate(sign, true) && isNotOfType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, true);
if (isCandidate(sign, false) && isNotOfType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, false);
}
}
@Inject(at = @At("HEAD"), method = "shouldRender", cancellable = true)
private static void shouldRender(BlockPos pos, int signColor, CallbackInfoReturnable<Boolean> cir) {
if (PictureSignConfig.enabled && client.world != null && PictureSignType.hasPicture((SignBlockEntity) client.world.getBlockEntity(pos))) cir.setReturnValue(true);
if (PictureSignConfig.enabled && client.world != null && hasPicture((SignBlockEntity) client.world.getBlockEntity(pos))) cir.setReturnValue(true);
}
@Unique
@Override
@@ -47,6 +50,6 @@ public abstract class MixinSignBlockEntityRenderer implements BlockEntityRendere
@Unique
@Override
public boolean rendersOutsideBoundingBox(SignBlockEntity sign) {
return PictureSignConfig.enabled && PictureSignType.hasPicture(sign);
return PictureSignConfig.enabled && hasPicture(sign);
}
}

View File

@@ -19,7 +19,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Objects;
import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID;
import static eu.midnightdust.picturesign.PictureSignClient.id;
@Mixin(AbstractSignEditScreen.class)

View File

@@ -2,7 +2,6 @@ package eu.midnightdust.picturesign.render;
import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.picturesign.PictureSignClient;
import eu.midnightdust.picturesign.config.PictureSignConfig;
import eu.midnightdust.picturesign.util.GIFHandler;
import eu.midnightdust.picturesign.util.IrisCompat;
@@ -13,32 +12,55 @@ import eu.midnightdust.picturesign.util.PictureSignType;
import eu.midnightdust.picturesign.util.PictureURLUtils;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferRenderer;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.state.property.Properties;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import java.net.MalformedURLException;
import java.util.Iterator;
import static eu.midnightdust.picturesign.PictureSignClient.client;
import static eu.midnightdust.picturesign.PictureSignClient.hasWaterMedia;
import static eu.midnightdust.picturesign.PictureSignClient.id;
import static eu.midnightdust.picturesign.util.PictureSignType.*;
import static eu.midnightdust.picturesign.util.PictureSignType.GIF;
import static eu.midnightdust.picturesign.util.PictureSignType.PICTURE;
import static eu.midnightdust.picturesign.util.PictureSignType.getType;
public class PictureSignRenderer {
private boolean isSafeUrl;
private boolean isSafeJsonUrl;
public void render(SignBlockEntity signBlockEntity, MatrixStack matrixStack, int light, int overlay, boolean front) {
@Nullable private Text errorMessage;
public static final Text ERROR = Text.translatable("picturesign.error");
public static final Text MISSING_VLC = ERROR.copy().append(Text.translatable("picturesign.error.missingVLC"));
public static final Text MISSING_WATERMEDIA = ERROR.copy().append(Text.translatable("picturesign.error.missingWatermedia"));
public static final Text IMAGE_NOT_FOUND = ERROR.copy().append(Text.translatable("picturesign.error.imageNotFound"));
public static final Text UNKNOWN_FILETYPE = ERROR.copy().append(Text.translatable("picturesign.error.unknownFiletype"));
public static final Text UNKNOWN_SIGNTYPE = ERROR.copy().append(Text.translatable("picturesign.error.unknownSigntype"));
public static final Text UNSAFE_JSON_URL = ERROR.copy().append(Text.translatable("picturesign.error.unsafeJsonUrl"));
public static final Text UNSAFE_URL = ERROR.copy().append(Text.translatable("picturesign.error.unsafeUrl"));
public static final Identifier RAW_TEXTURE = id("internal_raw_texture");
public void render(SignBlockEntity signBlockEntity, MatrixStack matrixStack, VertexConsumerProvider vertices, int light, int overlay, boolean front) {
errorMessage = null;
PictureSignType type = getType(signBlockEntity, front);
String url = PictureURLUtils.getLink(signBlockEntity, front);
PictureInfo info = null;
@@ -51,21 +73,21 @@ public class PictureSignRenderer {
if (!isSafeJsonUrl) isSafeJsonUrl = jsonUrl.startsWith(safe);
});
if (url.endsWith(".json") || isSafeJsonUrl) {
if (PictureSignConfig.safeMode) {
if (!isSafeJsonUrl) return;
}
if (PictureSignConfig.safeMode && !isSafeJsonUrl) errorMessage = UNSAFE_JSON_URL;
info = PictureURLUtils.infoFromJson(url);
if (info == null) return;
url = info.url();
if (errorMessage == null) {
info = PictureURLUtils.infoFromJson(url);
if (info == null) return;
url = info.url();
if (!url.contains("://")) {
url = "https://" + url;
if (!url.contains("://")) {
url = "https://" + url;
}
}
}
if (type == PICTURE && !url.contains(".png") && !url.contains(".jpg") && !url.contains(".jpeg") && !url.startsWith("rp:")) return;
if (type == GIF && !url.contains(".gif")) return;
if (type == PICTURE && !url.contains(".png") && !url.contains(".jpg") && !url.contains(".jpeg") && !url.startsWith("rp:")) errorMessage = UNKNOWN_FILETYPE;
if (type == GIF && !url.contains(".gif")) errorMessage = UNKNOWN_FILETYPE;
if (PictureSignConfig.safeMode && !url.startsWith("file:") && !url.startsWith("rp:")) {
isSafeUrl = false;
String finalUrl = url;
@@ -84,9 +106,10 @@ public class PictureSignRenderer {
if (!isSafeUrl) isSafeUrl = finalUrl.startsWith(safe);
});
}
if (!isSafeUrl) return;
if (!isSafeUrl) errorMessage = UNSAFE_URL;
}
if ((!PictureSignConfig.enableMultimediaSigns || !MediaHandler.hasValidImplementation()) && type != PICTURE) return;
if ((!PictureSignConfig.enableMultimediaSigns || !MediaHandler.hasValidImplementation()) && type != PICTURE) errorMessage = MISSING_WATERMEDIA;
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://");
}
@@ -97,7 +120,7 @@ public class PictureSignRenderer {
MediaHandler mediaHandler = null;
GIFHandler gifHandler = null;
if (MediaHandler.hasValidImplementation()) {
if (errorMessage == null && MediaHandler.hasValidImplementation()) {
if (type.isVideo || type.isAudio) mediaHandler = MediaHandler.getOrCreate(videoId, pos);
else if (type == GIF && hasWaterMedia) gifHandler = GIFHandler.getOrCreate(videoId);
else {
@@ -160,12 +183,13 @@ public class PictureSignRenderer {
// Download the picture data
PictureDownloader.PictureData data = null;
if (type == PICTURE) {
if (errorMessage == null && type == PICTURE) {
data = PictureDownloader.getInstance().getPicture(url);
if (data == null || data.identifier == null) return;
if (data == null || data.identifier == null) errorMessage = IMAGE_NOT_FOUND;
}
else if (mediaHandler != null) {
try {
if (!mediaHandler.isReady()) errorMessage = MISSING_VLC;
else {
if (!mediaHandler.hasMedia() && !mediaHandler.playbackStarted) {
mediaHandler.play(url, type.isVideo);
if (info != null && info.start() > 0) mediaHandler.setTime(info.start());
@@ -173,29 +197,22 @@ public class PictureSignRenderer {
mediaHandler.setRepeat(true);
}
} catch (Exception e) {
PictureSignClient.LOGGER.error(e);
return;
}
if (info != null && info.volume() >= 0) mediaHandler.setMaxVolume(info.volume());
mediaHandler.setVolumeBasedOnDistance();
if (info != null && info.start() > 0 && mediaHandler.getTime() < info.start()) mediaHandler.setTime(info.start());
if (info != null && info.end() > 0 && mediaHandler.getTime() > info.end()) {
if (type.isLooped) mediaHandler.setTime(info.start() > 0 ? info.start() : 0);
else mediaHandler.stop();
if (info != null && info.volume() >= 0) mediaHandler.setMaxVolume(info.volume());
mediaHandler.setVolumeBasedOnDistance();
if (info != null && info.start() > 0 && mediaHandler.getTime() < info.start())
mediaHandler.setTime(info.start());
if (info != null && info.end() > 0 && mediaHandler.getTime() > info.end()) {
if (type.isLooped) mediaHandler.setTime(info.start() > 0 ? info.start() : 0);
else mediaHandler.stop();
}
}
}
else if (type == GIF && gifHandler != null) {
try {
if (!gifHandler.hasMedia() && !gifHandler.playbackStarted) {
gifHandler.play(url);
}
} catch (MalformedURLException e) {
PictureSignClient.LOGGER.error(e);
return;
if (!gifHandler.hasMedia() && !gifHandler.playbackStarted) {
gifHandler.play(url);
}
}
else return;
else if (errorMessage == null) errorMessage = UNKNOWN_SIGNTYPE;
if (type.isAudio) return;
@@ -237,36 +254,29 @@ public class PictureSignRenderer {
}
else RenderSystem.setShader(GameRenderer::getPositionColorTexLightmapProgram);
Identifier texture = null;
if (type == PICTURE) {
texture = data.identifier;
}
else if (type.isVideo && mediaHandler != null) {
boolean hasVideoTexture = false;
if (mediaHandler.isWorking()) {
int rawTexture = mediaHandler.getTexture();
if (rawTexture != -1) {
RenderSystem.setShaderTexture(0, rawTexture);
hasVideoTexture = true;
Identifier texture = getMissingTexture();
if (errorMessage == null) {
if (type == PICTURE) {
assert data != null;
texture = data.identifier;
} else if (type.isVideo && mediaHandler != null) {
if (mediaHandler.isWorking()) {
int rawTexture = mediaHandler.getTexture();
if (rawTexture != -1) {
RenderSystem.setShaderTexture(0, rawTexture);
texture = RAW_TEXTURE;
}
}
} else if (gifHandler != null) {
if (gifHandler.isWorking()) {
RenderSystem.setShaderTexture(0, gifHandler.getTexture());
texture = RAW_TEXTURE;
}
}
if (!hasVideoTexture) {
var id = MediaHandler.getMissingTexture();
if (id == null) return;
texture = id;
}
}
else if (gifHandler != null) {
if (gifHandler.isWorking()) RenderSystem.setShaderTexture(0, gifHandler.getTexture());
else {
var id = MediaHandler.getMissingTexture();
if (id == null) return;
texture = id;
}
}
else return;
if (texture != null) RenderSystem.setShaderTexture(0, texture);
if (texture == null) return;
if (texture != RAW_TEXTURE) RenderSystem.setShaderTexture(0, texture);
if (PictureSignConfig.translucency) RenderSystem.enableBlend();
else RenderSystem.disableBlend();
@@ -292,9 +302,32 @@ public class PictureSignRenderer {
BufferRenderer.drawWithGlobalProgram(buffer.end());
if (errorMessage != null) renderErrorMessage(client.textRenderer, matrixStack, vertices, width, height);
matrixStack.pop();
RenderSystem.disableBlend();
RenderSystem.disableDepthTest();
}
private void renderErrorMessage(TextRenderer textRenderer, MatrixStack matrices, VertexConsumerProvider vertices, float width, float height) {
float scale = Math.min(width, height) / 100;
matrices.translate(0, height, 1.005f);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180));
matrices.scale(scale,scale,scale);
int wrappedY = 0;
for(Iterator<OrderedText> textIterator = textRenderer.wrapLines(errorMessage, MathHelper.floor(width/scale)).iterator(); textIterator.hasNext(); wrappedY += 9) {
renderTextWithShadow(textIterator.next(), wrappedY, textRenderer, matrices.peek().getPositionMatrix(), vertices);
}
}
private void renderTextWithShadow(OrderedText text, int wrappedY, TextRenderer textRenderer, Matrix4f matrix, VertexConsumerProvider vertices) {
textRenderer.draw(text, 0, wrappedY, 0xFFFFFF, false, matrix, vertices, TextRenderer.TextLayerType.POLYGON_OFFSET, 0, 15728880);
matrix.translate(0, 0, 0.025f);
textRenderer.draw(text, 1, wrappedY + 1, 0x555555, false, matrix, vertices, TextRenderer.TextLayerType.POLYGON_OFFSET, 0, 15728880);
matrix.translate(0, 0, -0.025f);
}
public static Identifier getMissingTexture() {
if (PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.TRANSPARENT)) return null;
return PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.BLACK) ?
(id("textures/black.png")) : (TextureManager.MISSING_IDENTIFIER);
}
}

View File

@@ -5,15 +5,28 @@ import eu.midnightdust.picturesign.config.PictureSignConfig;
import eu.midnightdust.picturesign.util.NetworkUtil;
import eu.midnightdust.picturesign.util.PictureSignType;
import eu.midnightdust.picturesign.util.PictureURLUtils;
import net.minecraft.block.*;
import net.minecraft.block.AbstractSignBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.HangingSignBlock;
import net.minecraft.block.SignBlock;
import net.minecraft.block.WallHangingSignBlock;
import net.minecraft.block.WoodType;
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.*;
import net.minecraft.client.render.*;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
@@ -277,25 +290,25 @@ public class PictureSignHelperScreen extends Screen {
DiffuseLighting.disableGuiDepthLighting();
String enabledWebsites = "";
if (PictureSignConfig.safeMode) {
if (type.equals(PictureSignType.PICTURE)) enabledWebsites = " (imgur.com/imgbb.com/iili.io/pictshare.net)";
else if (type.equals(PictureSignType.GIF)) enabledWebsites = " (imgur.com/tenor.com)";
else if (type.isVideo) enabledWebsites = " (youtube.com/youtu.be/vimeo.com)";
else if (type.isAudio) enabledWebsites = " (youtube.com/youtu.be/vimeo.com/freesound.org)";
if (type.equals(PictureSignType.PICTURE)) enabledWebsites = "(imgur.com/imgbb.com/iili.io/pictshare.net)";
else if (type.equals(PictureSignType.GIF)) enabledWebsites = "(imgur.com/tenor.com)";
else if (type.isVideo) enabledWebsites = "(youtube.com/youtu.be/vimeo.com)";
else if (type.isAudio) enabledWebsites = "(youtube.com/youtu.be/vimeo.com/freesound.org)";
}
if (type.isAudio) pictureWidgets.forEach(widget -> widget.active = false);
else pictureWidgets.forEach(widget -> widget.active = true);
context.drawTextWithShadow(textRenderer, Text.of("Link" + enabledWebsites),
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.link", enabledWebsites),
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);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.width"),this.width / 2 - 175, this.height / 5 + 60, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.height"),this.width / 2 - 140, this.height / 5 + 60, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.pos_x"),this.width / 2 - 105, this.height / 5 + 60, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.pos_y"),this.width / 2 - 70, this.height / 5 + 60, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.pos_z"),this.width / 2 - 35, this.height / 5 + 60, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.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.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.rot_x"),this.width / 2 - 175, this.height / 5 + 92, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.rot_y"),this.width / 2 - 103, this.height / 5 + 92, -8816268);
context.drawTextWithShadow(textRenderer, Text.translatable("picturesign.helper.rot_z"),this.width / 2 - 30, this.height / 5 + 92, -8816268);
}
context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 40, 16777215);
MatrixStack matrices = context.getMatrices();

View File

@@ -3,10 +3,8 @@ package eu.midnightdust.picturesign.util;
import me.srrapero720.watermedia.api.image.ImageAPI;
import me.srrapero720.watermedia.api.image.ImageCache;
import me.srrapero720.watermedia.api.math.MathAPI;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
@@ -47,8 +45,8 @@ public class GIFHandler {
gifPlayers.clear();
}
public void play(String url) throws MalformedURLException {
this.player = ImageAPI.getCache(url, MinecraftClient.getInstance());
public void play(String url) {
this.player = ImageAPI.getCache(url, client);
player.load();
this.playbackStarted = true;
}

View File

@@ -1,7 +1,6 @@
package eu.midnightdust.picturesign.util;
import eu.midnightdust.picturesign.config.PictureSignConfig;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@@ -11,8 +10,6 @@ import java.util.Map;
import static eu.midnightdust.picturesign.PictureSignClient.client;
import static eu.midnightdust.picturesign.PictureSignClient.hasWaterMedia;
import static eu.midnightdust.picturesign.PictureSignClient.id;
public abstract class MediaHandler {
public static Map<Identifier, MediaHandler> mediaHandlers = new HashMap<>();
@@ -88,12 +85,10 @@ public abstract class MediaHandler {
public int getTexture() {
return -1;
}
public boolean isReady() {
return false;
}
public boolean isWorking() {
return false;
}
public static Identifier getMissingTexture() {
if (PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.TRANSPARENT)) return null;
return PictureSignConfig.missingImageMode.equals(PictureSignConfig.MissingImageMode.BLACK) ?
(id("textures/black.png")) : (TextureManager.MISSING_IDENTIFIER);
}
}

View File

@@ -4,13 +4,13 @@ import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.text.Text;
public enum PictureSignType {
NONE(Text.empty(), "", false, false, false),
PICTURE(Text.of("Image"), "!PS:", false, false, false),
GIF(Text.of("GIF"), "!GS:", true, false, false),
VIDEO(Text.of("Video"), "!VS:", false, true, false),
LOOPED_VIDEO(Text.of("Video Loop"), "!LS:", true, true, false),
AUDIO(Text.of("Audio"), "!AS:", false, false, true),
LOOPED_AUDIO(Text.of("Audio Loop"), "!ALS:", true, false, true);
NONE(Text.empty(), "", false, false, false),
PICTURE(Text.translatable("picturesign.type.image"), "!PS:", false, false, false),
GIF(Text.translatable("picturesign.type.gif"), "!GS:", true, false, false),
VIDEO(Text.translatable("picturesign.type.video"), "!VS:", false, true, false),
LOOPED_VIDEO(Text.translatable("picturesign.type.video_loop"), "!LS:", true, true, false),
AUDIO(Text.translatable("picturesign.type.audio"), "!AS:", false, false, true),
LOOPED_AUDIO(Text.translatable("picturesign.type.audio_loop"), "!ALS:", true, false, true);
public final Text name;
public final String format;
@@ -50,6 +50,9 @@ public enum PictureSignType {
};
}
public static boolean isCandidate(SignBlockEntity signBlockEntity, boolean front) {
return signBlockEntity.getText(front).getMessage(0,false).getString().startsWith("!");
}
public static boolean isNotOfType(SignBlockEntity signBlockEntity, PictureSignType type, boolean front) {
return getType(signBlockEntity, front) != type;
}

View File

@@ -1,5 +1,6 @@
package eu.midnightdust.picturesign.util;
import me.srrapero720.watermedia.api.player.PlayerAPI;
import me.srrapero720.watermedia.api.player.SyncBasePlayer;
import me.srrapero720.watermedia.api.player.SyncMusicPlayer;
import me.srrapero720.watermedia.api.player.SyncVideoPlayer;
@@ -9,6 +10,8 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL11;
import static eu.midnightdust.picturesign.PictureSignClient.client;
public class WaterMediaHandler extends MediaHandler {
private SyncBasePlayer player;
@@ -54,7 +57,7 @@ public class WaterMediaHandler extends MediaHandler {
@Override
public void play(String url, boolean isVideo) {
this.player = isVideo ? new SyncVideoPlayer(MinecraftClient.getInstance()) : new SyncMusicPlayer();
this.player = isVideo ? new SyncVideoPlayer(client) : new SyncMusicPlayer();
mediaHandlers.put(id, this);
if (player.isBroken()) return;
player.start(url);
@@ -85,6 +88,10 @@ public class WaterMediaHandler extends MediaHandler {
return -1;
}
@Override
public boolean isReady() {
return PlayerAPI.isReady();
}
@Override
public boolean isWorking() {
return mediaHandlers.containsKey(id) && mediaHandlers.get(id) instanceof WaterMediaHandler waterMediaHandler
&& waterMediaHandler.player != null && !waterMediaHandler.player.isBroken();

View File

@@ -2,6 +2,8 @@
"picturesign.midnightconfig.title":"PictureSign Konfiguration",
"picturesign.midnightconfig.enabled":"Aktiviere Bilder",
"picturesign.midnightconfig.enableMultimediaSigns":"Aktiviere Multimedia",
"picturesign.midnightconfig.audioDistanceMultiplier":"Audio-Distanz Multiplikator",
"picturesign.midnightconfig.translucency":"Aktiviere Lichtdurchlässigkeit",
"picturesign.midnightconfig.translucency.tooltip":"Lichtdurchlässigkeit funktioniert teilweise nicht richtig\nbei Block-Entities (und dementsprechend Schildern)",
"picturesign.midnightconfig.helperUi":"Aktiviere Hilfsoberfäche",
@@ -12,21 +14,37 @@
"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, dass du alles in Relation zu Schildern in der EBE Config deaktiviert hast!",
"picturesign.midnightconfig.safeProviders":"Sichere Anbieter",
"picturesign.midnightconfig.safeProviders":"Sichere Bildanbieter",
"picturesign.midnightconfig.safeGifProviders":"Sichere GIF-Anbieter",
"picturesign.midnightconfig.safeMultimediaProviders":"Sichere Multimedia-Anbieter",
"picturesign.midnightconfig.safeJsonProviders":"Sichere JSON-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",
"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"
"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",
"picturesign.type.image": "Bild",
"picturesign.helper.width": "Breite",
"picturesign.helper.height": "Höhe",
"picturesign.helper.mode": "Modus",
"picturesign.error": "FEHLER: ",
"picturesign.error.imageNotFound": "Das angegebene Bild konnte nicht gefunden werden.\nBist du offline oder ist die Website down?",
"picturesign.error.missingVLC": "VLC ist nicht installiert oder konnte nicht gefunden werden.",
"picturesign.error.missingWatermedia": "Installiere WATERMeDIA, um GIFs, Videos und Audios zu genießen.",
"picturesign.error.unknownFiletype": "Der Dateityp des Bildes wird nicht von PictureSign unterstützt.",
"picturesign.error.unknownSigntype": "Diese Version von PictureSign unterstützt keine Schilder des angegebenen Typen.",
"picturesign.error.unsafeJsonUrl": "Die angegebene JSON URL ist nicht als sicher bekannt.\nNutze einen anderen Anbieter oder ändere die PictureSign Konfiguration.",
"picturesign.error.unsafeUrl": "Die angegebene URL ist nicht als sicher bekannt.\nNutze einen anderen Anbieter oder ändere die PictureSign Konfiguration."
}

View File

@@ -22,8 +22,6 @@
"picturesign.midnightconfig.safeGifProviders":"Safe GIF Providers",
"picturesign.midnightconfig.safeMultimediaProviders":"Safe Multimedia Providers",
"picturesign.midnightconfig.safeJsonProviders":"Safe JSON 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",
@@ -37,5 +35,32 @@
"picturesign.midnightconfig.enum.PictureShader.PosTexCol":"PosTexCol",
"key.picturesign.copy_sign":"Copy Text from Sign",
"key.picturesign.edit_sign":"Edit Sign",
"key.categories.picturesign":"PictureSign"
"key.categories.picturesign":"PictureSign",
"picturesign.type.image": "Image",
"picturesign.type.gif": "GIF",
"picturesign.type.video": "Video",
"picturesign.type.video_loop": "Video Loop",
"picturesign.type.audio": "Audio",
"picturesign.type.audio_loop": "Audio Loop",
"picturesign.helper.link": "Link %s",
"picturesign.helper.width": "Width",
"picturesign.helper.height": "Height",
"picturesign.helper.pos_x": "PosX",
"picturesign.helper.pos_y": "PosY",
"picturesign.helper.pos_z": "PosZ",
"picturesign.helper.rot_x": "RotX",
"picturesign.helper.rot_y": "RotY",
"picturesign.helper.rot_z": "RotZ",
"picturesign.helper.mode": "Mode",
"picturesign.error": "ERROR: ",
"picturesign.error.imageNotFound": "The specified image could not be found.\nAre you offline or is the website down?",
"picturesign.error.missingVLC": "VLC is not installed or could not be found.",
"picturesign.error.missingWatermedia": "Install WATERMeDIA to enjoy GIFs, videos and audios.",
"picturesign.error.unknownFiletype": "The filetype of the specified image is not supported by PictureSign.",
"picturesign.error.unknownSigntype": "This version of PictureSign does not support signs of the specified type.",
"picturesign.error.unsafeJsonUrl": "The provided JSON URL is not known to be safe.\nUpload to a different provider or change the PictureSign config.",
"picturesign.error.unsafeUrl": "The provided URL is not known to be safe.\nUpload to a different provider or change the PictureSign config."
}

View File

@@ -12,7 +12,7 @@ curseforge_id=432008
modrinth_id=YQnwl5Vv
midnightlib_version=1.5.7
watermedia_version=2.0.63
watermedia_version=2.0.64
iris_version=1.6.17+1.20.4
# The latest Iris version causes the build to fail, but we don't need that anyway