package dev.isxander.yacl3.impl; import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.gui.image.ImageRenderer; import dev.isxander.yacl3.gui.image.ImageRendererManager; import dev.isxander.yacl3.gui.image.impl.AnimatedDynamicTextureImage; import dev.isxander.yacl3.gui.image.impl.DynamicTextureImage; import dev.isxander.yacl3.gui.image.impl.ResourceTextureImage; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.Validate; import java.nio.file.Path; import java.util.*; import java.util.concurrent.CompletableFuture; public record OptionDescriptionImpl(Component text, CompletableFuture> image) implements OptionDescription { public static class BuilderImpl implements Builder { private final List descriptionLines = new ArrayList<>(); private CompletableFuture> image = CompletableFuture.completedFuture(Optional.empty()); private boolean imageUnset = true; @Override public Builder text(Component... description) { this.descriptionLines.addAll(Arrays.asList(description)); return this; } @Override public Builder text(Collection lines) { this.descriptionLines.addAll(lines); return this; } @Override public Builder image(ResourceLocation image, int width, int height) { Validate.isTrue(imageUnset, "Image already set!"); Validate.isTrue(width > 0, "Width must be greater than 0!"); Validate.isTrue(height > 0, "Height must be greater than 0!"); this.image = ImageRendererManager.registerOrGetImage(image, () -> ResourceTextureImage.createFactory(image, 0, 0, width, height, width, height)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder image(ResourceLocation image, float u, float v, int width, int height, int textureWidth, int textureHeight) { Validate.isTrue(imageUnset, "Image already set!"); Validate.isTrue(width > 0, "Width must be greater than 0!"); Validate.isTrue(height > 0, "Height must be greater than 0!"); this.image = ImageRendererManager.registerOrGetImage(image, () -> ResourceTextureImage.createFactory(image, u, v, width, height, textureWidth, textureHeight)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder image(Path path, ResourceLocation uniqueLocation) { Validate.isTrue(imageUnset, "Image already set!"); this.image = ImageRendererManager.registerOrGetImage(uniqueLocation, () -> DynamicTextureImage.fromPath(path, uniqueLocation)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder gifImage(ResourceLocation image) { Validate.isTrue(imageUnset, "Image already set!"); this.image = ImageRendererManager.registerOrGetImage(image, () -> AnimatedDynamicTextureImage.createGIFFromTexture(image)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder gifImage(Path path, ResourceLocation uniqueLocation) { Validate.isTrue(imageUnset, "Image already set!"); this.image = ImageRendererManager.registerOrGetImage(uniqueLocation, () -> AnimatedDynamicTextureImage.createGIFFromPath(path, uniqueLocation)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder webpImage(ResourceLocation image) { Validate.isTrue(imageUnset, "Image already set!"); this.image = ImageRendererManager.registerOrGetImage(image, () -> AnimatedDynamicTextureImage.createWEBPFromTexture(image)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder webpImage(Path path, ResourceLocation uniqueLocation) { Validate.isTrue(imageUnset, "Image already set!"); this.image = ImageRendererManager.registerOrGetImage(uniqueLocation, () -> AnimatedDynamicTextureImage.createWEBPFromPath(path, uniqueLocation)).thenApply(Optional::of); imageUnset = false; return this; } @Override public Builder customImage(CompletableFuture> image) { Validate.notNull(image, "Image cannot be null!"); Validate.isTrue(imageUnset, "Image already set!"); this.image = image; this.imageUnset = false; return this; } @Override public OptionDescription build() { MutableComponent concatenatedDescription = Component.empty(); Iterator iter = descriptionLines.iterator(); while (iter.hasNext()) { concatenatedDescription.append(iter.next()); if (iter.hasNext()) concatenatedDescription.append("\n"); } return new OptionDescriptionImpl(concatenatedDescription, image); } } }