-
Notifications
You must be signed in to change notification settings - Fork 19
Zleub/texture provider #402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "frametime": 2 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| package com.wanderersoftherift.wotr.datagen; | ||
|
|
||
| import com.wanderersoftherift.wotr.WanderersOfTheRift; | ||
| import com.wanderersoftherift.wotr.datagen.textures.TextureGenerator; | ||
| import com.wanderersoftherift.wotr.datagen.textures.TextureGeneratorCollector; | ||
| import net.minecraft.data.CachedOutput; | ||
| import net.minecraft.data.DataProvider; | ||
| import net.minecraft.data.PackOutput; | ||
| import net.minecraft.resources.ResourceLocation; | ||
| import net.minecraft.server.packs.resources.ResourceManager; | ||
| import net.neoforged.neoforge.common.extensions.IModelProviderExtension; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.CompletableFuture; | ||
|
|
||
| public class WotrTextureProvider implements DataProvider, IModelProviderExtension { | ||
| static Map<Integer, Integer> processorBlockColorMap = new HashMap<>(); | ||
| private final ResourceManager resourceManager; | ||
| private final PackOutput.PathProvider texturePathProvider; | ||
|
|
||
| static { | ||
| processorBlockColorMap.put(15, 0x5EDFB2); | ||
| processorBlockColorMap.put(14, 0xC96C7E); | ||
| processorBlockColorMap.put(13, 0xA2DD7A); | ||
| processorBlockColorMap.put(12, 0xFFFFFF); | ||
| processorBlockColorMap.put(11, 0xF66FED); | ||
| processorBlockColorMap.put(10, 0xC773F2); | ||
| processorBlockColorMap.put(9, 0x609CF9); | ||
| processorBlockColorMap.put(8, 0x64D9F5); | ||
| processorBlockColorMap.put(7, 0x636C7E); | ||
| processorBlockColorMap.put(6, 0xC9D97E); | ||
| processorBlockColorMap.put(5, 0x646FF5); | ||
| processorBlockColorMap.put(4, 0x9360F9); | ||
| processorBlockColorMap.put(3, 0x63DA7E); | ||
| processorBlockColorMap.put(2, 0xCE7D67); | ||
| processorBlockColorMap.put(1, 0x888F9C); | ||
| } | ||
|
|
||
| enum TextureVariant { | ||
| Block(""), | ||
| DirectionPillar("directional_pillar"), | ||
| DirectionPillarTop("directional_pillar_top"), | ||
| Glass("glass"), | ||
| GlassPaneTop("glass_pane_top"), | ||
| Trapdoor("trapdoor"); | ||
|
|
||
| private final String suffix; | ||
|
|
||
| TextureVariant(String suffix) { | ||
| this.suffix = suffix; | ||
| } | ||
|
|
||
| String getSuffix() { | ||
| return this.suffix; | ||
| } | ||
| } | ||
|
|
||
| WotrTextureProvider(ResourceManager resourceManager, PackOutput output) { | ||
| this.texturePathProvider = output.createPathProvider(PackOutput.Target.RESOURCE_PACK, "textures"); | ||
| this.resourceManager = resourceManager; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull CompletableFuture<?> run(@NotNull CachedOutput cachedOutput) { | ||
| TextureGeneratorCollector textureCollector = new TextureGeneratorCollector(resourceManager, cachedOutput, | ||
| texturePathProvider); | ||
|
|
||
| this.registerTextures(new TextureGenerator(textureCollector)); | ||
|
|
||
| return textureCollector.save(); | ||
| } | ||
|
|
||
| public void registerTextures(TextureGenerator textureGenerator) { | ||
| processorBlockColorMap.forEach((number, color) -> { | ||
| // Make all processor blocks textures | ||
| Arrays.stream(TextureVariant.values()).toList().forEach((variant) -> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably could skip the |
||
| String sourcePath; | ||
| if (!Objects.equals(variant.getSuffix(), "")) { | ||
| sourcePath = "block/processor_block/processor_block_template_" + variant.getSuffix(); | ||
| } else { | ||
| sourcePath = "block/processor_block/processor_block_template"; | ||
| } | ||
|
|
||
| textureGenerator.tintGenerator( | ||
| ResourceLocation.fromNamespaceAndPath(WanderersOfTheRift.MODID, sourcePath), | ||
| ResourceLocation.fromNamespaceAndPath(WanderersOfTheRift.MODID, | ||
| sourcePath.replace("template", String.valueOf(number)).replace("processor_block/", "")), | ||
| color | ||
| ); | ||
| }); | ||
|
|
||
| // Make all fluid block textures | ||
| textureGenerator.tintGenerator( | ||
| ResourceLocation.withDefaultNamespace("block/water_flow"), | ||
| ResourceLocation.fromNamespaceAndPath(WanderersOfTheRift.MODID, "block/water_flow_" + number), color | ||
| ); | ||
|
|
||
| textureGenerator.tintGenerator( | ||
| ResourceLocation.withDefaultNamespace("block/water_still"), | ||
| ResourceLocation.fromNamespaceAndPath(WanderersOfTheRift.MODID, "block/water_still_" + number), | ||
| color | ||
| ); | ||
|
|
||
| }); | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull String getName() { | ||
| return "Wotr Texture Definition"; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package com.wanderersoftherift.wotr.datagen.textures; | ||
|
|
||
| import net.minecraft.resources.ResourceLocation; | ||
|
|
||
| import java.awt.Color; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public class TextureGenerator { | ||
| public final Consumer<TextureTransform> textureOutput; | ||
|
|
||
| public TextureGenerator(Consumer<TextureTransform> textureOutput) { | ||
| this.textureOutput = textureOutput; | ||
| } | ||
|
|
||
| public void tintGenerator(ResourceLocation sourcePath, ResourceLocation destinationPath, int color) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Little thing, but I would suggest
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, makes sense |
||
| this.textureOutput.accept(new TintTransform(sourcePath, destinationPath, color)); | ||
| } | ||
|
|
||
| public void tintGenerator(ResourceLocation sourcePath, ResourceLocation destinationPath, Color color) { | ||
| this.textureOutput.accept(new TintTransform(sourcePath, destinationPath, color)); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| package com.wanderersoftherift.wotr.datagen.textures; | ||
|
|
||
| import com.google.common.hash.Hashing; | ||
| import com.google.common.hash.HashingOutputStream; | ||
| import com.google.gson.JsonElement; | ||
| import com.mojang.serialization.JsonOps; | ||
| import com.wanderersoftherift.wotr.WanderersOfTheRift; | ||
| import net.minecraft.Util; | ||
| import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection; | ||
| import net.minecraft.data.CachedOutput; | ||
| import net.minecraft.data.DataProvider; | ||
| import net.minecraft.data.PackOutput; | ||
| import net.minecraft.resources.ResourceLocation; | ||
| import net.minecraft.server.packs.resources.Resource; | ||
| import net.minecraft.server.packs.resources.ResourceManager; | ||
| import net.minecraft.server.packs.resources.ResourceMetadata; | ||
|
|
||
| import javax.imageio.ImageIO; | ||
| import javax.imageio.stream.ImageInputStream; | ||
| import javax.imageio.stream.ImageOutputStream; | ||
| import java.awt.image.BufferedImage; | ||
| import java.io.ByteArrayOutputStream; | ||
| import java.io.InputStream; | ||
| import java.nio.file.Path; | ||
| import java.util.ArrayList; | ||
| import java.util.concurrent.CompletableFuture; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public class TextureGeneratorCollector implements Consumer<TextureTransform> { | ||
| private final ResourceManager resourceManager; | ||
| private final CachedOutput output; | ||
| private final PackOutput.PathProvider pathProvider; | ||
| private final ArrayList<TextureTransform> transforms; | ||
|
|
||
| public TextureGeneratorCollector(ResourceManager resourceManager, CachedOutput output, | ||
| PackOutput.PathProvider pathProvider) { | ||
| this.resourceManager = resourceManager; | ||
| this.transforms = new ArrayList<>(); | ||
| this.output = output; | ||
| this.pathProvider = pathProvider; | ||
| } | ||
|
|
||
| @Override | ||
| public void accept(TextureTransform textureTransform) { | ||
| transforms.add(textureTransform); | ||
| } | ||
|
|
||
| public CompletableFuture<?> applyTransform(TextureTransform transform) { | ||
| ResourceLocation resourceLocation = transform.sourcePath.withPrefix("textures/").withSuffix(".png"); | ||
| Path pathOut = pathProvider.file(transform.destinationPath, "png"); | ||
|
|
||
| ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); | ||
| HashingOutputStream hashingoutputstream = new HashingOutputStream(Hashing.sha1(), bytearrayoutputstream); | ||
|
|
||
| try { | ||
| Resource input = resourceManager.getResource(resourceLocation).orElseThrow(); | ||
| ResourceMetadata resourceMeta = input.metadata(); | ||
| AnimationMetadataSection textureMeta = resourceMeta.getSection(AnimationMetadataSection.TYPE).orElse(null); | ||
|
|
||
| InputStream r = input.open(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to ensure this is closed after use, either via a try-with-resources or an explicit close in a finally block.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, as the java doc stated, this stream is closed after use by |
||
|
|
||
| ImageInputStream imageInputStream = ImageIO.createImageInputStream(r); | ||
| BufferedImage image = ImageIO.read(imageInputStream); | ||
|
|
||
| int width = image.getWidth(); | ||
| int height = image.getHeight(); | ||
|
|
||
| BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | ||
| for (int x = 0; x < width; x++) { | ||
| for (int y = 0; y < height; y++) { | ||
| int transform1 = transform.transform(x, y, image.getRGB(x, y)); | ||
| out.setRGB(x, y, transform1); | ||
| } | ||
| } | ||
|
|
||
| ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(hashingoutputstream); | ||
| ImageIO.write(out, "png", imageOutputStream); | ||
|
|
||
| if (textureMeta != null) { | ||
| WanderersOfTheRift.LOGGER.info("{} has metadata", resourceLocation); | ||
| JsonElement json = AnimationMetadataSection.CODEC.encodeStart(JsonOps.INSTANCE, textureMeta) | ||
| .getOrThrow(); | ||
| DataProvider.saveStable(output, json, pathProvider.file(transform.destinationPath, "mcmeta")); | ||
| } | ||
|
|
||
| output.writeIfNeeded(pathOut, bytearrayoutputstream.toByteArray(), hashingoutputstream.hash()); | ||
|
|
||
| } catch (Exception e) { | ||
| WanderersOfTheRift.LOGGER.warn("WotrTextureProvider - Error with resource {}", resourceLocation); | ||
| } | ||
|
|
||
| return CompletableFuture.completedFuture(transform.destinationPath); | ||
| } | ||
|
|
||
| public CompletableFuture<?> applyTransformAsync(TextureTransform transform) { | ||
| return CompletableFuture.runAsync(() -> applyTransform(transform), | ||
| Util.backgroundExecutor().forName("saveStable")); | ||
| } | ||
|
|
||
| public CompletableFuture<?> save() { | ||
| WanderersOfTheRift.LOGGER.info("TextureGeneratorCollector save {}", transforms.size()); | ||
| return CompletableFuture | ||
| .allOf(transforms.stream().map(this::applyTransformAsync).toArray(CompletableFuture[]::new)); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we expecting duplicates in the long term?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I got this added at the point where I had both textures, the original and the generated one. It seems that gradle copies over the generated ones when running the game and fail if no duplicate strategy is in place. There's only one discord message from mcjty that address this issue so I feel like we should keep it somehow even commented out
Idk how you want to handle that, let me know