3 Commits

Author SHA1 Message Date
Martin Prokoph
92f950bb0c Update properties for release 2024-07-03 21:40:26 +02:00
Martin Prokoph
68f2d026ec Fix Java 17 2024-07-03 15:09:31 +02:00
Martin Prokoph
e13a5ad978 1.20.1 port
This will not receive any future updates
2024-07-03 15:03:23 +02:00
24 changed files with 302 additions and 317 deletions

View File

@@ -1,6 +1,6 @@
plugins { plugins {
id "architectury-plugin" version "3.4-SNAPSHOT" id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false
id "me.shedaniel.unified-publishing" version "0.1.+" apply false id "me.shedaniel.unified-publishing" version "0.1.+" apply false
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
} }
@@ -27,7 +27,7 @@ subprojects {
dependencies { dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
implementation "maven.modrinth:watermedia:${rootProject.watermedia_version}" implementation "com.github.SrRapero720.watermedia:build:${rootProject.watermedia_version}"
// The following line declares the mojmap mappings, you may use other mappings as well // The following line declares the mojmap mappings, you may use other mappings as well
//mappings loom.officialMojangMappings() //mappings loom.officialMojangMappings()
// The following line declares the yarn mappings you may select this one as well. // The following line declares the yarn mappings you may select this one as well.
@@ -58,7 +58,7 @@ allprojects {
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
options.encoding = "UTF-8" options.encoding = "UTF-8"
options.release = 21 options.release = 17
} }
ext { ext {
releaseChangelog = { releaseChangelog = {

View File

@@ -2,10 +2,6 @@ package eu.midnightdust.picturesign;
import eu.midnightdust.lib.util.PlatformFunctions; import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.config.PictureSignConfig;
import eu.midnightdust.picturesign.util.GIFHandler;
import eu.midnightdust.picturesign.util.MediaHandler;
import eu.midnightdust.picturesign.util.WaterGIFHandler;
import eu.midnightdust.picturesign.util.WaterMediaHandler;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
@@ -17,19 +13,16 @@ import org.lwjgl.glfw.GLFW;
public class PictureSignClient { public class PictureSignClient {
public static Logger LOGGER = LogManager.getLogger("PictureSign"); public static Logger LOGGER = LogManager.getLogger("PictureSign");
public static final String MOD_ID = "picturesign"; public static final String MOD_ID = "picturesign";
public static final boolean hasWaterMedia = PlatformFunctions.isModLoaded("watermedia");
public static String[] clipboard = new String[4]; public static String[] clipboard = new String[4];
public static final MinecraftClient client = MinecraftClient.getInstance(); public static final MinecraftClient client = MinecraftClient.getInstance();
public static final KeyBinding BINDING_COPY_SIGN = new KeyBinding("key.%s.copy_sign".formatted(MOD_ID), public static final KeyBinding BINDING_COPY_SIGN = new KeyBinding("key."+MOD_ID+".copy_sign",
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_U, "key.categories.%s".formatted(MOD_ID)); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_U, "key.categories."+MOD_ID);
public static void init() { public static void init() {
PictureSignConfig.init(MOD_ID, PictureSignConfig.class); PictureSignConfig.init(MOD_ID, PictureSignConfig.class);
if (PlatformFunctions.isModLoaded("watermedia")) {
MediaHandler.registerHandler(WaterMediaHandler::new);
GIFHandler.registerHandler(WaterGIFHandler::new);
}
} }
public static Identifier id(String path) { public static Identifier id(String path) {
return Identifier.of(MOD_ID, path); return new Identifier(MOD_ID, path);
} }
} }

View File

@@ -2,94 +2,47 @@ package eu.midnightdust.picturesign.config;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import eu.midnightdust.lib.config.MidnightConfig; import eu.midnightdust.lib.config.MidnightConfig;
import eu.midnightdust.lib.util.PlatformFunctions; import net.minecraft.client.gl.ShaderProgram;
import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.gl.ShaderProgramKeys;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import static eu.midnightdust.picturesign.PictureSignClient.id;
public class PictureSignConfig extends MidnightConfig { public class PictureSignConfig extends MidnightConfig {
private static final String GENERAL = "general"; private static final String general = "1general";
private static final String ADVANCED = "advanced"; private static final String advanced = "advanced";
private static final String EBE_MODID = "enhancedblockentities"; @Entry(category = general) public static boolean enabled = true;
private static final String WM_MODID = "watermedia"; @Entry(category = general) public static boolean enableMultimediaSigns = true;
private static final String IRIS_MODID = "iris"; @Entry(min = 0, max = 1000, isSlider = true, category = general) public static int audioDistanceMultiplier = 30;
@Entry(category = general) public static boolean translucency = false;
@Comment(centered = true, category = GENERAL) public static Comment _features; @Entry(category = general) public static boolean fullBrightPicture = false;
@Entry(category = GENERAL) public static boolean enabled = true; @Entry(category = general) public static boolean helperUi = true;
@Condition(requiredModId = WM_MODID) @Entry(category = general) public static boolean exceedVanillaLineLength = true;
@Entry(category = GENERAL) public static boolean enableMultimediaSigns = true; @Entry(category = advanced) public static boolean debug = false;
@Condition(requiredOption = "isWMLoaded", requiredValue = "false") @Entry(min = 1, max = 10, isSlider = true, category = advanced) public static int maxThreads = 4;
@Comment(category = GENERAL, centered = true) public static Comment wmNotice; @Entry(min = 0, max = 2048, isSlider = true, category = general) public static int signRenderDistance = 64;
@Entry(category = advanced) public static boolean safeMode = true;
@Comment(centered = true, category = GENERAL) public static Comment _behaviour; @Entry(category = advanced) public static List<String> safeProviders = Lists.newArrayList("https://i.imgur.com/", "https://i.ibb.co/", "https://pictshare.net/", "https://iili.io/");
@Entry(category = GENERAL) public static boolean helperUi = true; @Entry(category = advanced) public static List<String> safeGifProviders = Lists.newArrayList("https://i.imgur.com/", "https://media1.tenor.com/");
@Condition(requiredOption = "helperUi", visibleButLocked = true) @Entry(category = advanced) public static List<String> safeMultimediaProviders = Lists.newArrayList("https://youtube.com/", "https://www.youtube.com/", "https://youtu.be/","https://vimeo.com/");
@Entry(category = GENERAL) public static boolean exceedVanillaLineLength = true; @Entry(category = advanced) public static List<String> safeJsonProviders = Lists.newArrayList("https://github.com/", "https://gist.github.com/", "https://www.jsonkeeper.com/", "https://api.npoint.io/", "https://api.jsonsilo.com/");
@Entry(category = GENERAL) public static boolean translucency = false; @Comment(category = general) public static Comment ebeWarning;
@Entry(category = GENERAL) public static boolean fullBrightPicture = false; @Entry(category = advanced) public static MissingImageMode missingImageMode = MissingImageMode.BLACK;
@Entry(min = 0, max = 2048, isSlider = true, category = GENERAL) public static int signRenderDistance = 64; @Entry(category = advanced) public static PictureShader pictureShader = PictureShader.PosColTexLight;
@Condition(requiredModId = WM_MODID)
@Entry(min = 0, max = 1000, isSlider = true, category = GENERAL) public static int audioDistanceMultiplier = 30;
@Condition(requiredModId = EBE_MODID)
@Comment(category = GENERAL) public static Comment ebeWarning;
@Comment(centered = true, category = ADVANCED) public static Comment _workarounds;
@Entry(category = ADVANCED) public static MissingImageMode missingImageMode = MissingImageMode.BLACK;
@Condition(requiredModId = IRIS_MODID)
@Entry(category = ADVANCED) public static PictureShader pictureShader = PictureShader.PosColTexLight;
@Comment(centered = true, category = ADVANCED) public static Comment _misc;
@Entry(category = ADVANCED) public static boolean debug = false;
@Entry(min = 1, max = 10, isSlider = true, category = ADVANCED) public static int maxThreads = 4;
@Comment(centered = true, category = ADVANCED) public static Comment _security;
@Entry(category = ADVANCED) public static boolean safeMode = true;
@Condition(requiredOption = "safeMode")
@Entry(category = ADVANCED) public static List<String> safeProviders = Lists.newArrayList("https://i.imgur.com/", "https://i.ibb.co/", "https://pictshare.net/", "https://iili.io/");
@Condition(requiredModId = WM_MODID)
@Condition(requiredOption = "safeMode")
@Entry(category = ADVANCED) public static List<String> safeGifProviders = Lists.newArrayList("https://i.imgur.com/", "https://media1.tenor.com/");
@Condition(requiredModId = WM_MODID)
@Condition(requiredOption = "safeMode")
@Entry(category = ADVANCED) public static List<String> safeMultimediaProviders = Lists.newArrayList("https://youtube.com/", "https://www.youtube.com/", "https://youtu.be/","https://vimeo.com/");
@Condition(requiredOption = "safeMode")
@Entry(category = ADVANCED) public static List<String> safeJsonProviders = Lists.newArrayList("https://github.com/", "https://gist.github.com/", "https://www.jsonkeeper.com/", "https://api.npoint.io/", "https://api.jsonsilo.com/");
@Condition(requiredModId = "thismodhopefullydoesntexistwejustneedtohidetheentrywhilekeepingitaccessible")
@Entry(category = GENERAL) public static boolean isWMLoaded = PlatformFunctions.isModLoaded(WM_MODID);
public enum MissingImageMode { public enum MissingImageMode {
BLACK(id("textures/black.png")), BLACK, MISSING_TEXTURE, TRANSPARENT
MISSING_TEXTURE(TextureManager.MISSING_IDENTIFIER),
TRANSPARENT(null);
MissingImageMode(@Nullable Identifier missingTextureId) {
this.missingTextureId = missingTextureId;
}
@Nullable public final Identifier missingTextureId;
} }
public enum PictureShader { public enum PictureShader {
PosColTexLight(ShaderProgramKeys.POSITION_COLOR_TEX_LIGHTMAP), PosColTexLight(GameRenderer::getPositionColorTexLightmapProgram),
RenderTypeCutout(ShaderProgramKeys.RENDERTYPE_CUTOUT), RenderTypeCutout(GameRenderer::getRenderTypeCutoutProgram),
PosTex(ShaderProgramKeys.POSITION_TEX), PosTex(GameRenderer::getPositionTexProgram),
PosTexCol(ShaderProgramKeys.POSITION_TEX_COLOR); PosTexCol(GameRenderer::getPositionTexColorProgram);
PictureShader(ShaderProgramKey program) { PictureShader(Supplier<ShaderProgram> program) {
this.program = program; this.program = program;
} }
public final ShaderProgramKey program; public final Supplier<ShaderProgram> program;
}
public static void init(String modid, Class<? extends MidnightConfig> config) {
MidnightConfig.init(modid, config);
isWMLoaded = PlatformFunctions.isModLoaded(WM_MODID);
PictureSignConfig.write(modid);
} }
} }

View File

@@ -5,8 +5,8 @@ import eu.midnightdust.picturesign.render.PictureSignRenderer;
import eu.midnightdust.picturesign.util.PictureSignType; import eu.midnightdust.picturesign.util.PictureSignType;
import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.AbstractSignBlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@@ -17,15 +17,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static eu.midnightdust.picturesign.util.PictureSignType.isCandidate; import static eu.midnightdust.picturesign.util.PictureSignType.isCandidate;
import static eu.midnightdust.picturesign.util.PictureSignType.isNotOfType; import static eu.midnightdust.picturesign.util.PictureSignType.isNotOfType;
@Mixin(AbstractSignBlockEntityRenderer.class) @Mixin(HangingSignBlockEntityRenderer.class)
public abstract class MixinAbstractSignBlockEntityRenderer implements BlockEntityRenderer<SignBlockEntity> { public abstract class MixinHangingSignBlockEntityRenderer implements BlockEntityRenderer<SignBlockEntity> {
@Unique PictureSignRenderer picturesign$psRenderer = new PictureSignRenderer(); @Unique PictureSignRenderer psRenderer = new PictureSignRenderer();
@Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/block/entity/SignBlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;II)V") @Inject(at = @At("HEAD"), method = "render")
public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) { public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) {
if (PictureSignConfig.enabled) { if (PictureSignConfig.enabled) {
if (isCandidate(sign, true) && isNotOfType(sign, PictureSignType.NONE, true)) picturesign$psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, true); 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)) picturesign$psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, false); if (isCandidate(sign, false) && isNotOfType(sign, PictureSignType.NONE, false)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, false);
} }
} }
@Unique @Unique

View File

@@ -31,17 +31,17 @@ public abstract class MixinSignBlockEntityRenderer implements BlockEntityRendere
psRenderer = new PictureSignRenderer(); psRenderer = new PictureSignRenderer();
} }
// @Inject(at = @At("HEAD"), method = "render") @Inject(at = @At("HEAD"), method = "render")
// public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) { public void ps$onRender(SignBlockEntity sign, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, CallbackInfo ci) {
// if (PictureSignConfig.enabled && psRenderer != null) { if (PictureSignConfig.enabled && psRenderer != null) {
// if (isCandidate(sign, true) && isNotOfType(sign, PictureSignType.NONE, true)) psRenderer.render(sign, matrixStack, vertexConsumerProvider, light, overlay, true); 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); 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) @Inject(at = @At("HEAD"), method = "shouldRender", cancellable = true)
// private static void shouldRender(BlockPos pos, int signColor, CallbackInfoReturnable<Boolean> cir) { private static void shouldRender(BlockPos pos, int signColor, CallbackInfoReturnable<Boolean> cir) {
// if (PictureSignConfig.enabled && client.world != null && 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 @Unique
@Override @Override
public int getRenderDistance() { public int getRenderDistance() {

View File

@@ -3,10 +3,10 @@ package eu.midnightdust.picturesign.mixin;
import eu.midnightdust.picturesign.PictureSignClient; import eu.midnightdust.picturesign.PictureSignClient;
import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.config.PictureSignConfig;
import eu.midnightdust.picturesign.screen.PictureSignHelperScreen; import eu.midnightdust.picturesign.screen.PictureSignHelperScreen;
import eu.midnightdust.picturesign.screen.TextIconButtonWidget;
import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen; import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@@ -23,7 +23,7 @@ import static eu.midnightdust.picturesign.PictureSignClient.id;
@Mixin(AbstractSignEditScreen.class) @Mixin(AbstractSignEditScreen.class)
public abstract class MixinSignEditScreen extends Screen { public abstract class MixinSignEditScreen extends Screen {
@Shadow @Final protected SignBlockEntity blockEntity; @Shadow @Final private SignBlockEntity blockEntity;
@Shadow @Final private String[] messages; @Shadow @Final private String[] messages;
@Shadow @Final private boolean front; @Shadow @Final private boolean front;

View File

@@ -15,9 +15,9 @@ import eu.midnightdust.picturesign.util.records.PictureOffset;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gl.ShaderProgramKeys;
import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferRenderer; import net.minecraft.client.render.BufferRenderer;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormat;
@@ -32,14 +32,17 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import java.util.Iterator; import java.util.Iterator;
import static eu.midnightdust.picturesign.PictureSignClient.client; 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.PictureSignClient.id;
import static eu.midnightdust.picturesign.util.PictureSignType.GIF; import static eu.midnightdust.picturesign.util.PictureSignType.GIF;
import static eu.midnightdust.picturesign.util.PictureSignType.PICTURE; import static eu.midnightdust.picturesign.util.PictureSignType.PICTURE;
import static net.minecraft.client.texture.TextureManager.MISSING_IDENTIFIER;
public class PictureRenderer { public class PictureRenderer {
private boolean isSafeUrl; private boolean isSafeUrl;
@@ -93,9 +96,9 @@ public class PictureRenderer {
MediaHandler mediaHandler = null; MediaHandler mediaHandler = null;
GIFHandler gifHandler = null; GIFHandler gifHandler = null;
if (errorMessage == null) { if (errorMessage == null && MediaHandler.hasValidImplementation()) {
if ((type.isVideo || type.isAudio) && MediaHandler.hasValidImplementation()) mediaHandler = MediaHandler.getOrCreate(videoId, pos); if (type.isVideo || type.isAudio) mediaHandler = MediaHandler.getOrCreate(videoId, pos);
else if (type == GIF && GIFHandler.hasValidImplementation()) gifHandler = GIFHandler.getOrCreate(videoId); else if (type == GIF && hasWaterMedia) gifHandler = GIFHandler.getOrCreate(videoId);
else { else {
MediaHandler.closePlayer(videoId); MediaHandler.closePlayer(videoId);
GIFHandler.closePlayer(videoId); GIFHandler.closePlayer(videoId);
@@ -104,6 +107,8 @@ public class PictureRenderer {
if (isDisabledViaRedstone(blockEntity.getWorld(), pos)) { if (isDisabledViaRedstone(blockEntity.getWorld(), pos)) {
if (mediaHandler != null && mediaHandler.isWorking() && !mediaHandler.isStopped()) mediaHandler.stop(); if (mediaHandler != null && mediaHandler.isWorking() && !mediaHandler.isStopped()) mediaHandler.stop();
//PictureURLUtils.cachedJsonData.remove(url);
return; return;
} }
else if (mediaHandler != null && mediaHandler.isDeactivated) { else if (mediaHandler != null && mediaHandler.isDeactivated) {
@@ -121,7 +126,8 @@ public class PictureRenderer {
if (!mediaHandler.playbackStarted && !mediaHandler.hasMedia()) { if (!mediaHandler.playbackStarted && !mediaHandler.hasMedia()) {
mediaHandler.play(url, type.isVideo); mediaHandler.play(url, type.isVideo);
if (info != null && info.start() > 0) mediaHandler.setTime(info.start()); if (info != null && info.start() > 0) mediaHandler.setTime(info.start());
mediaHandler.setRepeat(type.isLooped); if (type.isLooped && !mediaHandler.hasMedia() && !mediaHandler.playbackStarted)
mediaHandler.setRepeat(true);
} }
if (info != null && info.volume() >= 0) mediaHandler.setMaxVolume(info.volume()); if (info != null && info.volume() >= 0) mediaHandler.setMaxVolume(info.volume());
@@ -148,16 +154,15 @@ public class PictureRenderer {
int l = PictureSignConfig.fullBrightPicture ? 15728880 : light; int l = PictureSignConfig.fullBrightPicture ? 15728880 : light;
if (PlatformFunctions.isModLoaded("iris") && IrisCompat.isShaderPackInUse()) if (PlatformFunctions.isModLoaded("iris") && IrisCompat.isShaderPackInUse())
RenderSystem.setShader(PictureSignConfig.pictureShader.program); RenderSystem.setShader(PictureSignConfig.pictureShader.program);
else RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR_TEX_LIGHTMAP); else RenderSystem.setShader(GameRenderer::getPositionColorTexLightmapProgram);
Identifier texture = PictureSignConfig.missingImageMode.missingTextureId; Identifier texture = getMissingTexture();
if (errorMessage == null) { if (errorMessage == null) {
if (type == PICTURE) { if (type == PICTURE) {
assert data != null; assert data != null;
texture = data.identifier; texture = data.identifier;
} else if (type.isVideo && mediaHandler != null) { } else if (type.isVideo && mediaHandler != null) {
if (mediaHandler.isWorking()) { if (mediaHandler.isWorking()) {
mediaHandler.preRender();
int rawTexture = mediaHandler.getTexture(); int rawTexture = mediaHandler.getTexture();
if (rawTexture != -1) { if (rawTexture != -1) {
RenderSystem.setShaderTexture(0, rawTexture); RenderSystem.setShaderTexture(0, rawTexture);
@@ -187,15 +192,16 @@ public class PictureRenderer {
matrixStack.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(dimensions.zRot())); matrixStack.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(dimensions.zRot()));
Matrix4f matrix4f = matrixStack.peek().getPositionMatrix(); Matrix4f matrix4f = matrixStack.peek().getPositionMatrix();
BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_LIGHT); BufferBuilder buffer = tessellator.getBuffer();
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR_TEXTURE_LIGHT);
buffer.vertex(matrix4f, dimensions.width(), 0.0F, 1.0F).color(255, 255, 255, 255).texture(1.0F, 1.0F).light(l).overlay(overlay); buffer.vertex(matrix4f, dimensions.width(), 0.0F, 1.0F).color(255, 255, 255, 255).texture(1.0F, 1.0F).light(l).overlay(overlay).next();
buffer.vertex(matrix4f, dimensions.width(), dimensions.height(), 1.0F).color(255, 255, 255, 255).texture(1.0F, 0.0F).light(l).overlay(overlay); buffer.vertex(matrix4f, dimensions.width(), dimensions.height(), 1.0F).color(255, 255, 255, 255).texture(1.0F, 0.0F).light(l).overlay(overlay).next();
buffer.vertex(matrix4f, 0.0F, dimensions.height(), 1.0F).color(255, 255, 255, 255).texture(0.0F, 0.0F).light(l).overlay(overlay); buffer.vertex(matrix4f, 0.0F, dimensions.height(), 1.0F).color(255, 255, 255, 255).texture(0.0F, 0.0F).light(l).overlay(overlay).next();
buffer.vertex(matrix4f, 0.0F, 0.0F, 1.0F).color(255, 255, 255, 255).texture(0.0F, 1.0F).light(l).overlay(overlay); buffer.vertex(matrix4f, 0.0F, 0.0F, 1.0F).color(255, 255, 255, 255).texture(0.0F, 1.0F).light(l).overlay(overlay).next();
BufferRenderer.drawWithGlobalProgram(buffer.end()); BufferRenderer.drawWithGlobalProgram(buffer.end());
@@ -221,6 +227,14 @@ public class PictureRenderer {
textRenderer.draw(text, 1, wrappedY + 1, 0x555555, false, matrix, vertices, TextRenderer.TextLayerType.POLYGON_OFFSET, 0, 15728880); textRenderer.draw(text, 1, wrappedY + 1, 0x555555, false, matrix, vertices, TextRenderer.TextLayerType.POLYGON_OFFSET, 0, 15728880);
matrix.translate(0, 0, -0.025f); matrix.translate(0, 0, -0.025f);
} }
private static final Identifier BLACK_TEXTURE = id("textures/black.png");
public @Nullable Identifier getMissingTexture() {
return switch (PictureSignConfig.missingImageMode) {
case BLACK -> BLACK_TEXTURE;
case MISSING_TEXTURE -> MISSING_IDENTIFIER;
default -> null;
};
}
public void checkJsonUrlSafety(String jsonUrl) { public void checkJsonUrlSafety(String jsonUrl) {
isSafeJsonUrl = false; isSafeJsonUrl = false;
PictureSignConfig.safeJsonProviders.forEach(safe -> { PictureSignConfig.safeJsonProviders.forEach(safe -> {

View File

@@ -5,7 +5,12 @@ import eu.midnightdust.picturesign.config.PictureSignConfig;
import eu.midnightdust.picturesign.util.NetworkUtil; import eu.midnightdust.picturesign.util.NetworkUtil;
import eu.midnightdust.picturesign.util.PictureSignType; import eu.midnightdust.picturesign.util.PictureSignType;
import eu.midnightdust.picturesign.util.PictureURLUtils; 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.block.entity.SignBlockEntity;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
@@ -16,10 +21,11 @@ import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget; import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.model.Model; import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.*; import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.block.entity.AbstractSignBlockEntityRenderer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer; import net.minecraft.client.render.block.entity.SignBlockEntityRenderer;
import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -44,7 +50,7 @@ public class PictureSignHelperScreen extends Screen {
private static final Identifier CLIPBOARD_ICON_TEXTURE = id("icon/clipboard"); private static final Identifier CLIPBOARD_ICON_TEXTURE = id("icon/clipboard");
private static final Identifier TRASHBIN_ICON_TEXTURE = id("icon/trashbin"); private static final Identifier TRASHBIN_ICON_TEXTURE = id("icon/trashbin");
private final SignBlockEntity sign; private final SignBlockEntity sign;
private Model model; private SignBlockEntityRenderer.SignModel model;
protected String[] text; protected String[] text;
private final boolean front; private final boolean front;
private final boolean isHanging; private final boolean isHanging;
@@ -159,7 +165,7 @@ public class PictureSignHelperScreen extends Screen {
pictureWidgets.add(posYWidget); pictureWidgets.add(posYWidget);
pictureWidgets.add(posZWidget); pictureWidgets.add(posZWidget);
if (text[2].matches("(.*\\d:.*\\d:.*\\d)")) addRotationWidgets(); if (text[2].matches("(.*\\d:.*\\d:.*\\d)")) addRotationWidgets();
this.model = SignBlockEntityRenderer.createSignModel(this.client.getLoadedEntityModels(), this.signType, !(sign.getCachedState().getBlock() instanceof WallSignBlock)); this.model = SignBlockEntityRenderer.createSignModel(this.client.getEntityModelLoader(), AbstractSignBlock.getWoodType(sign.getCachedState().getBlock()));
} }
public void applyPosition(String position, int index) { public void applyPosition(String position, int index) {
String[] dimensions = new String[5]; String[] dimensions = new String[5];
@@ -331,7 +337,7 @@ public class PictureSignHelperScreen extends Screen {
} }
float n = (float)(-this.client.textRenderer.getWidth(string) / 2); float n = (float)(-this.client.textRenderer.getWidth(string) / 2);
this.client.textRenderer.draw(Text.of(string), n, (float)(m * 10 - this.text.length * 5), i, false, matrix4f, immediate, TextRenderer.TextLayerType.NORMAL, 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);
} }
} }
@@ -366,9 +372,11 @@ public class PictureSignHelperScreen extends Screen {
matrices.scale(0.6666667F, -0.6666667F, -0.6666667F); matrices.scale(0.6666667F, -0.6666667F, -0.6666667F);
SpriteIdentifier spriteIdentifier = TexturedRenderLayers.getSignTextureId(AbstractSignBlock.getWoodType(state.getBlock())); SpriteIdentifier spriteIdentifier = TexturedRenderLayers.getSignTextureId(AbstractSignBlock.getWoodType(state.getBlock()));
Objects.requireNonNull(model); SignBlockEntityRenderer.SignModel var10002 = this.model;
VertexConsumer vertexConsumer = spriteIdentifier.getVertexConsumer(immediate, model::getLayer); Objects.requireNonNull(var10002);
this.model.render(matrices, vertexConsumer, 15728880, OverlayTexture.DEFAULT_UV); 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.pop();
matrices.translate(0.0, 0.3333333432674408, 0.046666666865348816); matrices.translate(0.0, 0.3333333432674408, 0.046666666865348816);
matrices.scale(0.010416667F, -0.010416667F, 0.010416667F); matrices.scale(0.010416667F, -0.010416667F, 0.010416667F);
@@ -376,7 +384,7 @@ public class PictureSignHelperScreen extends Screen {
else { else {
MatrixStack matrices = context.getMatrices(); MatrixStack matrices = context.getMatrices();
matrices.scale(4.5F, 4.5F, 1.0F); matrices.scale(4.5F, 4.5F, 1.0F);
context.drawTexture(RenderLayer::getGuiTextured, Identifier.ofVanilla("textures/gui/hanging_signs/" + this.signType.name() + ".png"), -8, -8, 0.0F, 0.0F, 16, 16, 16, 16); context.drawTexture(new Identifier("textures/gui/hanging_signs/" + this.signType.name() + ".png"), -8, -8, 0.0F, 0.0F, 16, 16, 16, 16);
} }
} }

View File

@@ -0,0 +1,98 @@
package eu.midnightdust.picturesign.screen;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public abstract class TextIconButtonWidget extends ButtonWidget {
protected final Identifier texture;
protected final int textureWidth;
protected final int textureHeight;
TextIconButtonWidget(int width, int height, Text message, int textureWidth, int textureHeight, Identifier texture, ButtonWidget.PressAction onPress, @Nullable ButtonWidget.NarrationSupplier narrationSupplier) {
super(0, 0, width, height, message, onPress, narrationSupplier == null ? DEFAULT_NARRATION_SUPPLIER : narrationSupplier);
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
this.texture = texture;
}
public static Builder builder(Text text, ButtonWidget.PressAction onPress, boolean hideLabel) {
return new Builder(text, onPress, hideLabel);
}
@Environment(EnvType.CLIENT)
public static class Builder {
private final Text text;
private final ButtonWidget.PressAction onPress;
private final boolean hideText;
private int width = 150;
private int height = 20;
@Nullable
private Identifier texture;
private int textureWidth;
private int textureHeight;
@Nullable
ButtonWidget.NarrationSupplier narrationSupplier;
public Builder(Text text, ButtonWidget.PressAction onPress, boolean hideText) {
this.text = text;
this.onPress = onPress;
this.hideText = hideText;
}
public Builder width(int width) {
this.width = width;
return this;
}
public Builder dimension(int width, int height) {
this.width = width;
this.height = height;
return this;
}
public Builder texture(Identifier texture, int width, int height) {
this.texture = texture;
this.textureWidth = width;
this.textureHeight = height;
return this;
}
public Builder narration(ButtonWidget.NarrationSupplier narrationSupplier) {
this.narrationSupplier = narrationSupplier;
return this;
}
public TextIconButtonWidget build() {
if (this.texture == null) {
throw new IllegalStateException("Sprite not set");
} else {
this.texture = new Identifier(texture.getNamespace(), "textures/gui/sprites/"+texture.getPath() +".png");
return new IconOnly(this.width, this.height, this.text, this.textureWidth, this.textureHeight, this.texture, this.onPress, this.narrationSupplier);
}
}
}
@Environment(EnvType.CLIENT)
public static class IconOnly extends TextIconButtonWidget {
protected IconOnly(int i, int j, Text text, int k, int l, Identifier identifier, ButtonWidget.PressAction pressAction, @Nullable ButtonWidget.NarrationSupplier narrationSupplier) {
super(i, j, text, k, l, identifier, pressAction, narrationSupplier);
}
@Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) {
super.renderButton(context, mouseX, mouseY, delta);
int i = this.getX() + this.getWidth() / 2 - this.textureWidth / 2;
int j = this.getY() + this.getHeight() / 2 - this.textureHeight / 2;
context.drawTexture(this.texture, i, j, 0, 0, this.textureWidth, this.textureHeight, this.textureWidth, this.textureHeight);
}
public void drawMessage(DrawContext context, TextRenderer textRenderer, int color) {
}
}
}

View File

@@ -1,63 +1,64 @@
package eu.midnightdust.picturesign.util; 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.util.Identifier; import net.minecraft.util.Identifier;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import static eu.midnightdust.picturesign.PictureSignClient.client;
public class GIFHandler { public class GIFHandler {
private static final List<Function<Identifier, GIFHandler>> implementations = new ArrayList<>(); public static Map<Identifier, GIFHandler> gifPlayers = new HashMap<>();
public static Map<Identifier, GIFHandler> gifHandlers = new HashMap<>();
public final Identifier id; public final Identifier id;
public boolean playbackStarted; public boolean playbackStarted;
private ImageCache player;
private long tick = 0L;
public GIFHandler(Identifier id) { private GIFHandler(Identifier id) {
System.out.println("New GIF handler :" + id);
this.id = id; this.id = id;
gifHandlers.put(id, this); gifPlayers.put(id, this);
}
public static void registerHandler(Function<Identifier, GIFHandler> handler) {
implementations.add(handler);
}
public static boolean hasValidImplementation() {
return !implementations.isEmpty();
} }
public static GIFHandler getOrCreate(Identifier id) { public static GIFHandler getOrCreate(Identifier id) {
if (gifHandlers.containsKey(id)) return gifHandlers.get(id); if (gifPlayers.containsKey(id)) return gifPlayers.get(id);
AtomicReference<GIFHandler> handler = new AtomicReference<>(); else return new GIFHandler(id);
implementations.forEach(impl -> {
handler.set(impl.apply(id));
});
return handler.get();
} }
public void tick() { public void tick() {
if (player != null && player.getRenderer() != null && tick < player.getRenderer().duration) tick += 1;
else tick = 0;
} }
public void closePlayer() { public void closePlayer() {
gifHandlers.remove(this.id); player.release();
player = null;
gifPlayers.remove(this.id);
} }
public static void closePlayer(Identifier videoId) { public static void closePlayer(Identifier videoId) {
if (gifHandlers.containsKey(videoId)) gifHandlers.get(videoId).closePlayer(); if (gifPlayers.containsKey(videoId)) gifPlayers.get(videoId).closePlayer();
} }
public static void closeAll() { public static void closeAll() {
gifHandlers.forEach((id, handler) -> handler.closePlayer()); gifPlayers.forEach((id, handler) -> handler.closePlayer());
gifHandlers.clear(); gifPlayers.clear();
} }
public void play(String url) { public void play(String url) {
this.player = ImageAPI.getCache(url, client);
player.load();
this.playbackStarted = true; this.playbackStarted = true;
} }
public boolean hasMedia() { public boolean hasMedia() {
return false; return player != null && player.getStatus() == ImageCache.Status.READY;
} }
public int getTexture() { public int getTexture() {
return -1; return player.getRenderer().texture(tick,
(MathAPI.tickToMs(client.getTickDelta())), true);
} }
public boolean isWorking() { public boolean isWorking() {
return false; if (player != null && player.getException() != null) player.getException().fillInStackTrace();
return player != null && player.getStatus() == ImageCache.Status.READY && player.getRenderer() != null;
} }
} }

View File

@@ -3,21 +3,16 @@ package eu.midnightdust.picturesign.util;
import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.config.PictureSignConfig;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.ApiStatus;
import org.watermedia.api.player.videolan.VideoPlayer;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import static eu.midnightdust.picturesign.PictureSignClient.client; import static eu.midnightdust.picturesign.PictureSignClient.client;
import static eu.midnightdust.picturesign.PictureSignClient.hasWaterMedia;
public abstract class MediaHandler { public abstract class MediaHandler {
private static final List<BiFunction<Identifier, BlockPos, MediaHandler>> implementations = new ArrayList<>();
public static Map<Identifier, MediaHandler> mediaHandlers = new HashMap<>(); public static Map<Identifier, MediaHandler> mediaHandlers = new HashMap<>();
public final Identifier id; public final Identifier id;
@@ -26,23 +21,19 @@ public abstract class MediaHandler {
public boolean isDeactivated; public boolean isDeactivated;
int maxVolume = 100; int maxVolume = 100;
public MediaHandler(Identifier id, BlockPos pos) { MediaHandler(Identifier id, BlockPos pos) {
this.id = id; this.id = id;
this.pos = pos; this.pos = pos;
} }
public static void registerHandler(BiFunction<Identifier, BlockPos, MediaHandler> handler) {
implementations.add(handler);
}
public static boolean hasValidImplementation() {
return !implementations.isEmpty();
}
public static MediaHandler getOrCreate(Identifier id, BlockPos pos) { public static MediaHandler getOrCreate(Identifier id, BlockPos pos) {
if (mediaHandlers.containsKey(id)) return mediaHandlers.get(id); if (mediaHandlers.containsKey(id)) return mediaHandlers.get(id);
AtomicReference<MediaHandler> handler = new AtomicReference<>(); else if (hasWaterMedia) return new WaterMediaHandler(id, pos);
implementations.forEach(impl -> { // Add new implementations here via Mixin
handler.set(impl.apply(id, pos)); else return null;
}); }
return handler.get(); public static boolean hasValidImplementation() { // Mixin here to add new Multimedia implementations
if (hasWaterMedia) return true;
else return false;
} }
public void setVolumeBasedOnDistance() { public void setVolumeBasedOnDistance() {
if (!isWorking() || client.player == null) return; if (!isWorking() || client.player == null) return;
@@ -53,11 +44,9 @@ public abstract class MediaHandler {
return; return;
} }
double distance = this.pos.getSquaredDistance(playerPos) / PictureSignConfig.audioDistanceMultiplier; double distance = this.pos.getSquaredDistance(playerPos) / PictureSignConfig.audioDistanceMultiplier;
setVolume((int) Math.clamp(maxVolume-distance, 0, 100)); setVolume((int) MathHelper.clamp(maxVolume-distance, 0, 100));
} }
@ApiStatus.Internal void setVolume(int volume) {}
public void setVolume(int volume) {} // Please use 'setMaxVolume' to adjust the playback volume
public void setMaxVolume(int volume) { public void setMaxVolume(int volume) {
maxVolume = volume; maxVolume = volume;
} }
@@ -65,7 +54,8 @@ public abstract class MediaHandler {
public void closePlayer() {} public void closePlayer() {}
public static void closePlayer(Identifier videoId) { public static void closePlayer(Identifier videoId) {
if (mediaHandlers.get(videoId) instanceof MediaHandler mediaHandler) mediaHandler.closePlayer(); MediaHandler mediaHandler = mediaHandlers.getOrDefault(videoId, null);
if (mediaHandler != null) mediaHandler.closePlayer();
} }
public static void closeAll() { public static void closeAll() {
mediaHandlers.forEach(((id, player) -> player.closePlayer())); mediaHandlers.forEach(((id, player) -> player.closePlayer()));
@@ -94,8 +84,6 @@ public abstract class MediaHandler {
} }
public void setTime(long value) { public void setTime(long value) {
} }
public void preRender() {
}
public int getTexture() { public int getTexture() {
return -1; return -1;
} }

View File

@@ -2,6 +2,7 @@ package eu.midnightdust.picturesign.util;
import eu.midnightdust.picturesign.PictureSignClient; import eu.midnightdust.picturesign.PictureSignClient;
import eu.midnightdust.picturesign.config.PictureSignConfig; import eu.midnightdust.picturesign.config.PictureSignConfig;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage; import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture; import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -9,12 +10,11 @@ import net.minecraft.util.Identifier;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.net.URI; import java.net.URL;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID; import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID;
import static eu.midnightdust.picturesign.PictureSignClient.client;
import static java.util.concurrent.Executors.newFixedThreadPool; import static java.util.concurrent.Executors.newFixedThreadPool;
public class PictureDownloader { public class PictureDownloader {
@@ -71,8 +71,8 @@ public class PictureDownloader {
service.submit(() -> { service.submit(() -> {
try { try {
BufferedInputStream in = new BufferedInputStream(URI.create(url).toURL().openStream()); BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());
File file = File.createTempFile(".%s".formatted(MOD_ID), "temp"); File file = File.createTempFile("."+MOD_ID, "temp");
file.deleteOnExit(); file.deleteOnExit();
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
@@ -93,7 +93,7 @@ public class PictureDownloader {
data.identifier = texture; data.identifier = texture;
} }
if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished downloading picture: {}", url); if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished downloading picture: " + url);
} catch (IOException error) { } catch (IOException error) {
PictureSignClient.LOGGER.error("Error downloading picture: " + error); PictureSignClient.LOGGER.error("Error downloading picture: " + error);
@@ -102,7 +102,7 @@ public class PictureDownloader {
} }
private void loadLocalPicture(String url) { private void loadLocalPicture(String url) {
String realPath = url.replace("file:", ""); String realPath = url.replace("file:", "");
if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Started loading local picture: {}", url); if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Started loading local picture: " + url);
this.cache.put(url, new PictureData(url)); this.cache.put(url, new PictureData(url));
service.submit(() -> { service.submit(() -> {
@@ -115,11 +115,11 @@ public class PictureDownloader {
} }
} catch (IOException error) { } catch (IOException error) {
PictureSignClient.LOGGER.error("Error loading local picture: {}", String.valueOf(error)); PictureSignClient.LOGGER.error("Error loading local picture: " + error);
} }
}); });
if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished loading local picture: {}", url); if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished loading local picture: " + url);
} }
private void loadResourcePackTexture(String url) { private void loadResourcePackTexture(String url) {
String realIdentifierPath = url.replace("rp:", ""); String realIdentifierPath = url.replace("rp:", "");
@@ -128,7 +128,7 @@ public class PictureDownloader {
if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Started loading resource pack picture: " + url); if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Started loading resource pack picture: " + url);
Identifier id = Identifier.tryParse(realIdentifierPath); Identifier id = Identifier.tryParse(realIdentifierPath);
if (id == null) { if (id == null) {
PictureSignClient.LOGGER.error("Unable to locate resource texture: {}", url); PictureSignClient.LOGGER.error("Unable to locate resource texture: " + url);
return; return;
} }
@@ -140,7 +140,7 @@ public class PictureDownloader {
} }
}); });
if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished loading resource pack picture: {}", url); if (PictureSignConfig.debug) PictureSignClient.LOGGER.info("Finished loading resource pack picture: " + url);
} }
private static Identifier convert2png(File file) throws IOException { private static Identifier convert2png(File file) throws IOException {
@@ -154,9 +154,8 @@ public class PictureDownloader {
NativeImage nativeImage = NativeImage.read(inputStream); NativeImage nativeImage = NativeImage.read(inputStream);
NativeImageBackedTexture nativeImageBackedTexture = new NativeImageBackedTexture(nativeImage); NativeImageBackedTexture nativeImageBackedTexture = new NativeImageBackedTexture(nativeImage);
Identifier textureId = PictureSignClient.id("picturesign/image_%s".formatted(file.hashCode())); return MinecraftClient.getInstance().getTextureManager().registerDynamicTexture("picturesign/image",
client.getTextureManager().registerTexture(textureId, nativeImageBackedTexture); nativeImageBackedTexture);
return textureId;
} }
} }

View File

@@ -1,52 +0,0 @@
package eu.midnightdust.picturesign.util;
import net.minecraft.util.Identifier;
import org.watermedia.api.image.ImageAPI;
import org.watermedia.api.image.ImageCache;
import org.watermedia.api.math.MathAPI;
import java.net.URI;
import static eu.midnightdust.picturesign.PictureSignClient.client;
public class WaterGIFHandler extends GIFHandler {
private ImageCache player;
private int tick = 0;
public WaterGIFHandler(Identifier id) {
super(id);
}
@Override
public void tick() {
if (player != null && player.getRenderer() != null && tick < player.getRenderer().duration) tick += 1;
else tick = 0;
}
@Override
public void closePlayer() {
player.release();
player = null;
super.closePlayer();
}
@Override
public void play(String url) {
this.player = ImageAPI.getCache(URI.create(url), client);
player.load();
super.play(url);
}
@Override
public boolean hasMedia() {
return player != null && player.getStatus() == ImageCache.Status.READY;
}
@Override
public int getTexture() {
return player.getRenderer().texture(tick,
(MathAPI.tickToMs(client.getRenderTickCounter().getTickDelta(true))), true);
}
@Override
public boolean isWorking() {
if (player != null && player.getException() != null) player.getException().fillInStackTrace();
return player != null && player.getStatus() == ImageCache.Status.READY && player.getRenderer() != null;
}
}

View File

@@ -1,28 +1,26 @@
package eu.midnightdust.picturesign.util; 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;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.watermedia.api.player.PlayerAPI;
import org.watermedia.api.player.videolan.BasePlayer;
import org.watermedia.api.player.videolan.MusicPlayer;
import org.watermedia.api.player.videolan.VideoPlayer;
import java.net.URI;
import static eu.midnightdust.picturesign.PictureSignClient.client; import static eu.midnightdust.picturesign.PictureSignClient.client;
public class WaterMediaHandler extends MediaHandler { public class WaterMediaHandler extends MediaHandler {
private BasePlayer player; private SyncBasePlayer player;
public WaterMediaHandler(Identifier id, BlockPos pos) { WaterMediaHandler(Identifier id, BlockPos pos) {
super(id, pos); super(id, pos);
mediaHandlers.put(id, this); mediaHandlers.put(id, this);
} }
@Override @Override
public void setVolume(int volume) { void setVolume(int volume) {
player.setVolume((int) (volume * MinecraftClient.getInstance().options.getSoundVolume(SoundCategory.MASTER))); player.setVolume((int) (volume * MinecraftClient.getInstance().options.getSoundVolume(SoundCategory.MASTER)));
} }
@@ -38,7 +36,7 @@ public class WaterMediaHandler extends MediaHandler {
@Override @Override
public void stop() { public void stop() {
player.stop(); player.stop();
super.stop(); isDeactivated = true;
} }
@Override @Override
public boolean isStopped() { public boolean isStopped() {
@@ -59,10 +57,10 @@ public class WaterMediaHandler extends MediaHandler {
@Override @Override
public void play(String url, boolean isVideo) { public void play(String url, boolean isVideo) {
this.player = isVideo ? new VideoPlayer(client) : new MusicPlayer(); this.player = isVideo ? new SyncVideoPlayer(client) : new SyncMusicPlayer();
mediaHandlers.put(id, this); mediaHandlers.put(id, this);
if (player.isBroken()) return; if (player.isBroken()) return;
player.start(URI.create(url)); player.start(url);
this.playbackStarted = true; this.playbackStarted = true;
} }
@Override @Override
@@ -82,15 +80,10 @@ public class WaterMediaHandler extends MediaHandler {
player.seekTo(value); player.seekTo(value);
} }
@Override @Override
public void preRender() {
if (player instanceof VideoPlayer videoPlayer) {
videoPlayer.preRender();
}
}
@Override
public int getTexture() { public int getTexture() {
if (player instanceof VideoPlayer videoPlayer) { if (player instanceof SyncVideoPlayer videoPlayer) {
return videoPlayer.texture(); int tex = videoPlayer.getGlTexture();
if (GL11.glIsTexture(tex)) return tex;
} }
return -1; return -1;
} }

View File

@@ -13,6 +13,7 @@
"picturesign.midnightconfig.signRenderDistance":"Schildsichtweite", "picturesign.midnightconfig.signRenderDistance":"Schildsichtweite",
"picturesign.midnightconfig.safeMode":"Sicherer Modus", "picturesign.midnightconfig.safeMode":"Sicherer Modus",
"picturesign.midnightconfig.safeMode.tooltip":"Lädt nur Bilder von vertrauten Seiten", "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 Bildanbieter", "picturesign.midnightconfig.safeProviders":"Sichere Bildanbieter",
"picturesign.midnightconfig.safeGifProviders":"Sichere GIF-Anbieter", "picturesign.midnightconfig.safeGifProviders":"Sichere GIF-Anbieter",
"picturesign.midnightconfig.safeMultimediaProviders":"Sichere Multimedia-Anbieter", "picturesign.midnightconfig.safeMultimediaProviders":"Sichere Multimedia-Anbieter",
@@ -21,18 +22,11 @@
"picturesign.midnightconfig.enum.MissingImageMode.BLACK":"Schwarz", "picturesign.midnightconfig.enum.MissingImageMode.BLACK":"Schwarz",
"picturesign.midnightconfig.enum.MissingImageMode.MISSING_TEXTURE":"Schwarz & Lila", "picturesign.midnightconfig.enum.MissingImageMode.MISSING_TEXTURE":"Schwarz & Lila",
"picturesign.midnightconfig.enum.MissingImageMode.TRANSPARENT":"Transparent", "picturesign.midnightconfig.enum.MissingImageMode.TRANSPARENT":"Transparent",
"picturesign.midnightconfig.ebeWarning": "§cDu benutzt die Mod 'Enhanced Block Entities' stelle sicher, dass du alles in Relation zu Schildern in der EBE Config deaktiviert hast!",
"picturesign.midnightconfig.wmNotice":"§5Um Video/Audio abzuspielen, installiere die WATERMeDIA mod und VLC Media Player",
"picturesign.midnightconfig._features": "§7\uD83E\uDEA7 Funktionen",
"picturesign.midnightconfig._behaviour": "§7\uD83D\uDDBC Verhalten",
"picturesign.midnightconfig._workarounds": "§7\uD83D\uDD27 Problemumgehung",
"picturesign.midnightconfig._misc": "§7\uD83D\uDCD0 Verschiedenes",
"picturesign.midnightconfig._security": "§7\uD83D\uDD10 Sicherheit",
"key.picturesign.copy_sign": "Text eines Schildes kopieren", "key.picturesign.copy_sign": "Text eines Schildes kopieren",
"key.picturesign.edit_sign":"Schild bearbeiten", "key.picturesign.edit_sign":"Schild bearbeiten",
"picturesign.midnightconfig.category.general": "Generell", "picturesign.midnightconfig.category.1general": "Generell",
"picturesign.midnightconfig.category.advanced": "Fortgeschritten", "picturesign.midnightconfig.category.advanced": "Fortgeschritten",
"picturesign.midnightconfig.fullBrightPicture": "Höchste Helligkeit", "picturesign.midnightconfig.fullBrightPicture": "Höchste Helligkeit",
"picturesign.midnightconfig.fullBrightPicture.tooltip": "Sorgt dafür, dass Bilder immer vollkommen beleuchtet dargestellt werden", "picturesign.midnightconfig.fullBrightPicture.tooltip": "Sorgt dafür, dass Bilder immer vollkommen beleuchtet dargestellt werden",

View File

@@ -1,6 +1,6 @@
{ {
"picturesign.midnightconfig.title":"PictureSign Config", "picturesign.midnightconfig.title":"PictureSign Config",
"picturesign.midnightconfig.category.general":"General", "picturesign.midnightconfig.category.1general":"General",
"picturesign.midnightconfig.category.advanced":"Advanced", "picturesign.midnightconfig.category.advanced":"Advanced",
"picturesign.midnightconfig.enabled":"Enable Pictures", "picturesign.midnightconfig.enabled":"Enable Pictures",
@@ -11,12 +11,13 @@
"picturesign.midnightconfig.fullBrightPicture":"Full-bright Pictures", "picturesign.midnightconfig.fullBrightPicture":"Full-bright Pictures",
"picturesign.midnightconfig.fullBrightPicture.tooltip":"Makes pictures always appear fully lit", "picturesign.midnightconfig.fullBrightPicture.tooltip":"Makes pictures always appear fully lit",
"picturesign.midnightconfig.helperUi":"Enable Helper UI", "picturesign.midnightconfig.helperUi":"Enable Helper UI",
"picturesign.midnightconfig.exceedVanillaLineLength":"Exceed Vanilla Line Length", "picturesign.midnightconfig.exceedVanillaLineLength":"Exceed vanilla line length",
"picturesign.midnightconfig.debug":"Debug Mode", "picturesign.midnightconfig.debug":"Debug mode",
"picturesign.midnightconfig.maxThreads":"Max Download Threads", "picturesign.midnightconfig.maxThreads":"Max download threads",
"picturesign.midnightconfig.signRenderDistance":"Sign Render Distance", "picturesign.midnightconfig.signRenderDistance":"Sign render distance",
"picturesign.midnightconfig.safeMode":"Safe Mode", "picturesign.midnightconfig.safeMode":"Safe mode",
"picturesign.midnightconfig.safeMode.tooltip":"Only load images from trusted providers", "picturesign.midnightconfig.safeMode.tooltip":"Only load images from trusted providers",
"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 Image Providers", "picturesign.midnightconfig.safeProviders":"Safe Image Providers",
"picturesign.midnightconfig.safeGifProviders":"Safe GIF Providers", "picturesign.midnightconfig.safeGifProviders":"Safe GIF Providers",
"picturesign.midnightconfig.safeMultimediaProviders":"Safe Multimedia Providers", "picturesign.midnightconfig.safeMultimediaProviders":"Safe Multimedia Providers",
@@ -32,14 +33,6 @@
"picturesign.midnightconfig.enum.PictureShader.PosTex":"PosTex", "picturesign.midnightconfig.enum.PictureShader.PosTex":"PosTex",
"picturesign.midnightconfig.enum.PictureShader.PosColTex":"PosColTex", "picturesign.midnightconfig.enum.PictureShader.PosColTex":"PosColTex",
"picturesign.midnightconfig.enum.PictureShader.PosTexCol":"PosTexCol", "picturesign.midnightconfig.enum.PictureShader.PosTexCol":"PosTexCol",
"picturesign.midnightconfig.ebeWarning":"§cYou are using the mod 'Enhanced Block Entities' make sure to disable anything sign-related in it's config!",
"picturesign.midnightconfig.wmNotice":"§5To enable multimedia support, install the WATERMeDIA mod and VLC Media Player",
"picturesign.midnightconfig._features": "§7\uD83E\uDEA7 Features",
"picturesign.midnightconfig._behaviour": "§7\uD83D\uDDBC Behaviour",
"picturesign.midnightconfig._workarounds": "§7\uD83D\uDD27 Workarounds",
"picturesign.midnightconfig._misc": "§7\uD83D\uDCD0 Miscellaneous",
"picturesign.midnightconfig._security": "§7\uD83D\uDD10 Security",
"key.picturesign.copy_sign":"Copy Text from Sign", "key.picturesign.copy_sign":"Copy Text from Sign",
"key.picturesign.edit_sign":"Edit Sign", "key.picturesign.edit_sign":"Edit Sign",
"key.categories.picturesign":"PictureSign", "key.categories.picturesign":"PictureSign",

View File

@@ -4,7 +4,7 @@
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"client": [ "client": [
"MixinSignBlockEntityRenderer", "MixinSignBlockEntityRenderer",
"MixinAbstractSignBlockEntityRenderer", "MixinHangingSignBlockEntityRenderer",
"MixinSignEditScreen", "MixinSignEditScreen",
"MixinSignBlockEntity" "MixinSignBlockEntity"
], ],

View File

@@ -36,7 +36,7 @@ public class PictureSignClientFabric implements ClientModInitializer {
} }
}); });
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
GIFHandler.gifHandlers.forEach(((identifier, handler) -> handler.tick())); GIFHandler.gifPlayers.forEach(((identifier, handler) -> handler.tick()));
if (!BINDING_COPY_SIGN.isPressed()) return; if (!BINDING_COPY_SIGN.isPressed()) return;
BINDING_COPY_SIGN.setPressed(false); BINDING_COPY_SIGN.setPressed(false);
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.BLOCK) return; if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.BLOCK) return;

View File

@@ -35,9 +35,6 @@
"recommends": { "recommends": {
"watermedia": "*" "watermedia": "*"
}, },
"breaks": {
"watermedia": "<2.1.0"
},
"mixins": [ "mixins": [
"picturesign.mixins.json" "picturesign.mixins.json"
] ]

View File

@@ -1,26 +1,26 @@
org.gradle.jvmargs=-Xmx2048M org.gradle.jvmargs=-Xmx2048M
minecraft_version=1.21.4 minecraft_version=1.20.1
yarn_mappings=1.21.4+build.1 yarn_mappings=1.20.1+build.10
enabled_platforms=fabric,neoforge enabled_platforms=fabric
archives_base_name=picturesign archives_base_name=picturesign
mod_version=2.1.0 mod_version=2.0.0-1.20.1
maven_group=eu.midnightdust maven_group=eu.midnightdust
release_type=release release_type=alpha
curseforge_id=533897 curseforge_id=533897
modrinth_id=9WP2dmkk modrinth_id=9WP2dmkk
midnightlib_version=1.7.2+1.21.4 midnightlib_version=1.4.1
watermedia_version=2.1.24 watermedia_version=2.0.64
iris_version=1.6.17+1.20.4 iris_version=1.6.17+1.20.4
# The latest Iris version causes the build to fail, but we don't need that anyway # The latest Iris version causes the build to fail, but we don't need that anyway
fabric_loader_version=0.16.9 fabric_loader_version=0.15.11
fabric_api_version=0.111.0+1.21.4 fabric_api_version=0.92.2+1.20.1
neoforge_version=21.4.10-beta neoforge_version=21.0.14-beta
yarn_mappings_patch_neoforge_version = 1.21+build.4 yarn_mappings_patch_neoforge_version = 1.21+build.4
quilt_loader_version=0.19.0-beta.18 quilt_loader_version=0.19.0-beta.18

View File

@@ -38,7 +38,7 @@ public class PictureSignClientGameEvents {
} }
@SubscribeEvent @SubscribeEvent
public static void endClientTick(ClientTickEvent.Post event) { public static void endClientTick(ClientTickEvent.Post event) {
GIFHandler.gifHandlers.forEach(((identifier, handler) -> handler.tick())); GIFHandler.gifPlayers.forEach(((identifier, handler) -> handler.tick()));
if (!BINDING_COPY_SIGN.isPressed()) return; if (!BINDING_COPY_SIGN.isPressed()) return;
BINDING_COPY_SIGN.setPressed(false); BINDING_COPY_SIGN.setPressed(false);
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.BLOCK) return; if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.BLOCK) return;

View File

@@ -1,14 +1,20 @@
package eu.midnightdust.picturesign.neoforge; package eu.midnightdust.picturesign.neoforge;
import eu.midnightdust.picturesign.PictureSignClient; import eu.midnightdust.picturesign.PictureSignClient;
import net.minecraft.resource.ResourcePackProfile;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
import org.apache.commons.compress.utils.Lists;
import java.util.List;
import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID; import static eu.midnightdust.picturesign.PictureSignClient.MOD_ID;
@SuppressWarnings("all") @SuppressWarnings("all")
@Mod(value = MOD_ID, dist = Dist.CLIENT) @Mod(value = MOD_ID, dist = Dist.CLIENT)
public class PictureSignClientNeoForge { public class PictureSignClientNeoForge {
public static List<ResourcePackProfile> defaultEnabledPacks = Lists.newArrayList();
public PictureSignClientNeoForge() { public PictureSignClientNeoForge() {
PictureSignClient.init(); PictureSignClient.init();
} }

View File

@@ -16,21 +16,21 @@ Use signs to display custom images and videos completely client-side!
[[mixins]] [[mixins]]
config = "picturesign.mixins.json" config = "picturesign.mixins.json"
[[dependencies.picturesign]] [[dependencies.visualoverhaul]]
modId = "neoforge" modId = "neoforge"
mandatory = true mandatory = true
versionRange = "[21.0,)" versionRange = "[21.0,)"
ordering = "NONE" ordering = "NONE"
side = "BOTH" side = "BOTH"
[[dependencies.picturesign]] [[dependencies.visualoverhaul]]
modId = "minecraft" modId = "minecraft"
mandatory = true mandatory = true
versionRange = "[1.21,)" versionRange = "[1.21,)"
ordering = "NONE" ordering = "NONE"
side = "BOTH" side = "BOTH"
[[dependencies.picturesign]] [[dependencies.visualoverhaul]]
modId = "midnightlib" modId = "midnightlib"
mandatory = true mandatory = true
versionRange = "[1.0,)" versionRange = "[1.0,)"

View File

@@ -10,6 +10,6 @@ pluginManagement {
include("common") include("common")
include("fabric") include("fabric")
//include("quilt") //include("quilt")
include("neoforge") //include("neoforge")
rootProject.name = "picturesign" rootProject.name = "picturesign"