diff --git a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/PngToTgaMappings.java b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/PngToTgaMappings.java new file mode 100644 index 0000000..eefd54d --- /dev/null +++ b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/PngToTgaMappings.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", new Mapping(WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/PackConverter + * + */ + +package org.geysermc.pack.converter.converter.texture; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +// TODO: This should really be a JSON file +public final class PngToTgaMappings { + private static final Map MAPPINGS = new HashMap<>() { + { + put("textures/blocks/cactus_bottom.png", new TgaMapping("textures/blocks/cactus_bottom.tga")); + put("textures/blocks/cactus_side.png", new TgaMapping("textures/blocks/cactus_side.tga")); + put("textures/blocks/cactus_top.png", new TgaMapping("textures/blocks/cactus_top.tga")); + put("textures/blocks/double_plant_fern_bottom.png", new TgaMapping("textures/blocks/double_plant_fern_bottom.tga")); + put("textures/blocks/double_plant_fern_top.png", new TgaMapping("textures/blocks/double_plant_fern_top.tga")); + put("textures/blocks/double_plant_grass_bottom.png", new TgaMapping("textures/blocks/double_plant_grass_bottom.tga")); + put("textures/blocks/double_plant_grass_top.png", new TgaMapping("textures/blocks/double_plant_grass_top.tga")); + put("textures/blocks/double_plant_syringa_bottom.png", new TgaMapping("textures/blocks/double_plant_syringa_bottom.tga")); + put("textures/blocks/double_plant_syringa_top.png", new TgaMapping("textures/blocks/double_plant_syringa_top.tga")); + put("textures/blocks/fern.png", new TgaMapping("textures/blocks/fern.tga")); + put("textures/blocks/fern_carried.png", new TgaMapping("textures/blocks/fern_carried.tga")); + put("textures/blocks/grass_side.png", new TgaMapping("textures/blocks/grass_side.tga")); + put("textures/blocks/grass_side_snowed.png", new TgaMapping("textures/blocks/grass_side_snowed.tga", true)); + put("textures/blocks/grindstone_pivot.png", new TgaMapping("textures/blocks/grindstone_pivot.tga")); + put("textures/blocks/grindstone_round.png", new TgaMapping("textures/blocks/grindstone_round.tga")); + put("textures/blocks/grindstone_side.png", new TgaMapping("textures/blocks/grindstone_side.tga")); + put("textures/blocks/kelp_a.png", new TgaMapping("textures/blocks/kelp_a.tga")); + put("textures/blocks/kelp_b.png", new TgaMapping("textures/blocks/kelp_b.tga")); + put("textures/blocks/kelp_c.png", new TgaMapping("textures/blocks/kelp_c.tga")); + put("textures/blocks/kelp_d.png", new TgaMapping("textures/blocks/kelp_d.tga")); + put("textures/blocks/kelp_top.png", new TgaMapping("textures/blocks/kelp_top.tga")); + put("textures/blocks/kelp_top_bulb.png", new TgaMapping("textures/blocks/kelp_top_bulb.tga")); + put("textures/blocks/leaves_acacia.png", new TgaMapping("textures/blocks/leaves_acacia.tga")); + put("textures/blocks/leaves_acacia_carried.png", new TgaMapping("textures/blocks/leaves_acacia_carried.tga")); + put("textures/blocks/leaves_big_oak.png", new TgaMapping("textures/blocks/leaves_big_oak.tga")); + put("textures/blocks/leaves_big_oak_carried.png", new TgaMapping("textures/blocks/leaves_big_oak_carried.tga")); + put("textures/blocks/leaves_birch.png", new TgaMapping("textures/blocks/leaves_birch.tga")); + put("textures/blocks/leaves_birch_carried.png", new TgaMapping("textures/blocks/leaves_birch_carried.tga")); + put("textures/blocks/leaves_jungle.png", new TgaMapping("textures/blocks/leaves_jungle.tga")); + put("textures/blocks/leaves_jungle_carried.png", new TgaMapping("textures/blocks/leaves_jungle_carried.tga")); + put("textures/blocks/leaves_oak.png", new TgaMapping("textures/blocks/leaves_oak.tga")); + put("textures/blocks/leaves_oak_carried.png", new TgaMapping("textures/blocks/leaves_oak_carried.tga")); + put("textures/blocks/leaves_spruce.png", new TgaMapping("textures/blocks/leaves_spruce.tga")); + put("textures/blocks/leaves_spruce_carried.png", new TgaMapping("textures/blocks/leaves_spruce_carried.tga")); + put("textures/blocks/reeds.png", new TgaMapping("textures/blocks/reeds.tga")); + put("textures/blocks/scaffolding_bottom.png", new TgaMapping("textures/blocks/scaffolding_bottom.tga")); + put("textures/blocks/scaffolding_side.png", new TgaMapping("textures/blocks/scaffolding_side.tga")); + put("textures/blocks/scaffolding_top.png", new TgaMapping("textures/blocks/scaffolding_top.tga")); + put("textures/blocks/seagrass_doubletall_bottom_a.png", new TgaMapping("textures/blocks/seagrass_doubletall_bottom_a.tga")); + put("textures/blocks/seagrass_doubletall_bottom_b.png", new TgaMapping("textures/blocks/seagrass_doubletall_bottom_b.tga")); + put("textures/blocks/seagrass_doubletall_top_a.png", new TgaMapping("textures/blocks/seagrass_doubletall_top_a.tga")); + put("textures/blocks/seagrass_doubletall_top_b.png", new TgaMapping("textures/blocks/seagrass_doubletall_top_b.tga")); + put("textures/blocks/stonecutter2_saw.png", new TgaMapping("textures/blocks/stonecutter2_saw.tga")); + put("textures/blocks/tallgrass.png", new TgaMapping("textures/blocks/tallgrass.tga", true)); + put("textures/blocks/tallgrass_carried.png", new TgaMapping("textures/blocks/tallgrass_carried.tga")); + put("textures/entity/blaze.png", new TgaMapping("textures/entity/blaze.tga")); + put("textures/entity/phantom.png", new TgaMapping("textures/entity/phantom.tga")); + put("textures/entity/banner/banner.png", new TgaMapping("textures/entity/banner/banner.tga")); + put("textures/entity/banner/banner_pattern_illager.png", new TgaMapping("textures/entity/banner/banner_pattern_illager.tga")); + put("textures/entity/banner_base.png", new TgaMapping("textures/entity/banner/banner_base.tga")); + put("textures/entity/banner/border.png", new TgaMapping("textures/entity/banner/banner_border.tga")); + put("textures/entity/banner/bricks.png", new TgaMapping("textures/entity/banner/banner_bricks.tga")); + put("textures/entity/banner/circle.png", new TgaMapping("textures/entity/banner/banner_circle.tga")); + put("textures/entity/banner/creeper.png", new TgaMapping("textures/entity/banner/banner_creeper.tga")); + put("textures/entity/banner/cross.png", new TgaMapping("textures/entity/banner/banner_cross.tga")); + put("textures/entity/banner/curly_border.png", new TgaMapping("textures/entity/banner/banner_curly_border.tga")); + put("textures/entity/banner/diagonal_left.png", new TgaMapping("textures/entity/banner/banner_diagonal_left.tga")); + put("textures/entity/banner/diagonal_right.png", new TgaMapping("textures/entity/banner/banner_diagonal_right.tga")); + put("textures/entity/banner/diagonal_up_left.png", new TgaMapping("textures/entity/banner/banner_diagonal_up_left.tga")); + put("textures/entity/banner/diagonal_up_right.png", new TgaMapping("textures/entity/banner/banner_diagonal_up_right.tga")); + put("textures/entity/banner/flower.png", new TgaMapping("textures/entity/banner/banner_flower.tga")); + put("textures/entity/banner/gradient.png", new TgaMapping("textures/entity/banner/banner_gradient.tga")); + put("textures/entity/banner/gradient_up.png", new TgaMapping("textures/entity/banner/banner_gradient_up.tga")); + put("textures/entity/banner/half_horizontal.png", new TgaMapping("textures/entity/banner/banner_half_horizontal.tga")); + put("textures/entity/banner/half_horizontal_bottom.png", new TgaMapping("textures/entity/banner/banner_half_horizontal_bottom.tga")); + put("textures/entity/banner/half_vertical.png", new TgaMapping("textures/entity/banner/banner_half_vertical.tga")); + put("textures/entity/banner/half_vertical_right.png", new TgaMapping("textures/entity/banner/banner_half_vertical_right.tga")); + put("textures/entity/banner/mojang.png", new TgaMapping("textures/entity/banner/banner_mojang.tga")); + put("textures/entity/banner/piglin.png", new TgaMapping("textures/entity/banner/banner_piglin.tga")); + put("textures/entity/banner/rhombus.png", new TgaMapping("textures/entity/banner/banner_rhombus.tga")); + put("textures/entity/banner/skull.png", new TgaMapping("textures/entity/banner/banner_skull.tga")); + put("textures/entity/banner/small_stripes.png", new TgaMapping("textures/entity/banner/banner_small_stripes.tga")); + put("textures/entity/banner/square_bottom_left.png", new TgaMapping("textures/entity/banner/banner_square_bottom_left.tga")); + put("textures/entity/banner/square_bottom_right.png", new TgaMapping("textures/entity/banner/banner_square_bottom_right.tga")); + put("textures/entity/banner/square_top_left.png", new TgaMapping("textures/entity/banner/banner_square_top_left.tga")); + put("textures/entity/banner/square_top_right.png", new TgaMapping("textures/entity/banner/banner_square_top_right.tga")); + put("textures/entity/banner/straight_cross.png", new TgaMapping("textures/entity/banner/banner_straight_cross.tga")); + put("textures/entity/banner/stripe_bottom.png", new TgaMapping("textures/entity/banner/banner_stripe_bottom.tga")); + put("textures/entity/banner/stripe_center.png", new TgaMapping("textures/entity/banner/banner_stripe_center.tga")); + put("textures/entity/banner/stripe_downleft.png", new TgaMapping("textures/entity/banner/banner_stripe_downleft.tga")); + put("textures/entity/banner/stripe_downright.png", new TgaMapping("textures/entity/banner/banner_stripe_downright.tga")); + put("textures/entity/banner/stripe_left.png", new TgaMapping("textures/entity/banner/banner_stripe_left.tga")); + put("textures/entity/banner/stripe_middle.png", new TgaMapping("textures/entity/banner/banner_stripe_middle.tga")); + put("textures/entity/banner/stripe_right.png", new TgaMapping("textures/entity/banner/banner_stripe_right.tga")); + put("textures/entity/banner/stripe_top.png", new TgaMapping("textures/entity/banner/banner_stripe_top.tga")); + put("textures/entity/banner/triangle_bottom.png", new TgaMapping("textures/entity/banner/banner_triangle_bottom.tga")); + put("textures/entity/banner/triangle_top.png", new TgaMapping("textures/entity/banner/banner_triangle_top.tga")); + put("textures/entity/banner/triangles_bottom.png", new TgaMapping("textures/entity/banner/banner_triangles_bottom.tga")); + put("textures/entity/banner/triangles_top.png", new TgaMapping("textures/entity/banner/banner_triangles_top.tga")); + put("textures/entity/cat/allblackcat_tame.png", new TgaMapping("textures/entity/cat/allblackcat_tame.tga")); + put("textures/entity/cat/britishshorthair_tame.png", new TgaMapping("textures/entity/cat/britishshorthair_tame.tga")); + put("textures/entity/cat/calico_tame.png", new TgaMapping("textures/entity/cat/calico_tame.tga")); + put("textures/entity/cat/graytabby_tame.png", new TgaMapping("textures/entity/cat/graytabby_tame.tga")); + put("textures/entity/cat/jellie_tame.png", new TgaMapping("textures/entity/cat/jellie_tame.tga")); + put("textures/entity/cat/ocelot_tame.png", new TgaMapping("textures/entity/cat/ocelot_tame.tga")); + put("textures/entity/cat/persian_tame.png", new TgaMapping("textures/entity/cat/persian_tame.tga")); + put("textures/entity/cat/ragdoll_tame.png", new TgaMapping("textures/entity/cat/ragdoll_tame.tga")); + put("textures/entity/cat/redtabby_tame.png", new TgaMapping("textures/entity/cat/redtabby_tame.tga")); + put("textures/entity/cat/siamesecat_tame.png", new TgaMapping("textures/entity/cat/siamesecat_tame.tga")); + put("textures/entity/cat/tabby_tame.png", new TgaMapping("textures/entity/cat/tabby_tame.tga")); + put("textures/entity/cat/tuxedo_tame.png", new TgaMapping("textures/entity/cat/tuxedo_tame.tga")); + put("textures/entity/cat/white_tame.png", new TgaMapping("textures/entity/cat/white_tame.tga")); + put("textures/entity/dragon/dragon.png", new TgaMapping("textures/entity/dragon/dragon.tga")); + put("textures/entity/enderman/enderman.png", new TgaMapping("textures/entity/enderman/enderman.tga")); + put("textures/entity/ghast/ghast_shooting.png", new TgaMapping("textures/entity/ghast/ghast_shooting.tga")); + put("textures/entity/horse/armor/horse_armor_leather.png", new TgaMapping("textures/entity/horse/armor/horse_armor_leather.tga")); + put("textures/entity/horse2/armor/horse_armor_leather.png", new TgaMapping("textures/entity/horse2/armor/horse_armor_leather.tga")); + put("textures/entity/sheep/sheep.png", new TgaMapping("textures/entity/sheep/sheep.tga")); + put("textures/entity/slime/magmacube.png", new TgaMapping("textures/entity/slime/magmacube.tga")); + put("textures/entity/spider/cave_spider.png", new TgaMapping("textures/entity/spider/cave_spider.tga")); + put("textures/entity/spider/spider.png", new TgaMapping("textures/entity/spider/spider.tga")); + put("textures/entity/villager2/professions/armorer.png", new TgaMapping("textures/entity/villager2/professions/armorer.tga")); + put("textures/entity/villager2/professions/butcher.png", new TgaMapping("textures/entity/villager2/professions/butcher.tga")); + put("textures/entity/villager2/professions/cartographer.png", new TgaMapping("textures/entity/villager2/professions/cartographer.tga")); + put("textures/entity/villager2/professions/cleric.png", new TgaMapping("textures/entity/villager2/professions/cleric.tga")); + put("textures/entity/villager2/professions/farmer.png", new TgaMapping("textures/entity/villager2/professions/farmer.tga")); + put("textures/entity/villager2/professions/fisherman.png", new TgaMapping("textures/entity/villager2/professions/fisherman.tga")); + put("textures/entity/villager2/professions/fletcher.png", new TgaMapping("textures/entity/villager2/professions/fletcher.tga")); + put("textures/entity/villager2/professions/leatherworker.png", new TgaMapping("textures/entity/villager2/professions/leatherworker.tga")); + put("textures/entity/villager2/professions/librarian.png", new TgaMapping("textures/entity/villager2/professions/librarian.tga")); + put("textures/entity/villager2/professions/nitwit.png", new TgaMapping("textures/entity/villager2/professions/nitwit.tga")); + put("textures/entity/villager2/professions/shepherd.png", new TgaMapping("textures/entity/villager2/professions/shepherd.tga")); + put("textures/entity/villager2/professions/stonemason.png", new TgaMapping("textures/entity/villager2/professions/stonemason.tga")); + put("textures/entity/villager2/professions/toolsmith.png", new TgaMapping("textures/entity/villager2/professions/toolsmith.tga")); + put("textures/entity/villager2/professions/unskilled.png", new TgaMapping("textures/entity/villager2/professions/unskilled.tga")); + put("textures/entity/villager2/professions/weaponsmith.png", new TgaMapping("textures/entity/villager2/professions/weaponsmith.tga")); + put("textures/entity/wolf/wolf_tame.png", new TgaMapping("textures/entity/wolf/wolf_tame.tga")); + put("textures/entity/zombie/drowned.png", new TgaMapping("textures/entity/zombie/drowned.tga")); + put("textures/entity/zombie_villager2/professions/armorer.png", new TgaMapping("textures/entity/zombie_villager2/professions/armorer.tga")); + put("textures/entity/zombie_villager2/professions/butcher.png", new TgaMapping("textures/entity/zombie_villager2/professions/butcher.tga")); + put("textures/entity/zombie_villager2/professions/cartographer.png", new TgaMapping("textures/entity/zombie_villager2/professions/cartographer.tga")); + put("textures/entity/zombie_villager2/professions/cleric.png", new TgaMapping("textures/entity/zombie_villager2/professions/cleric.tga")); + put("textures/entity/zombie_villager2/professions/farmer.png", new TgaMapping("textures/entity/zombie_villager2/professions/farmer.tga")); + put("textures/entity/zombie_villager2/professions/fisherman.png", new TgaMapping("textures/entity/zombie_villager2/professions/fisherman.tga")); + put("textures/entity/zombie_villager2/professions/fletcher.png", new TgaMapping("textures/entity/zombie_villager2/professions/fletcher.tga")); + put("textures/entity/zombie_villager2/professions/leatherworker.png", new TgaMapping("textures/entity/zombie_villager2/professions/leatherworker.tga")); + put("textures/entity/zombie_villager2/professions/librarian.png", new TgaMapping("textures/entity/zombie_villager2/professions/librarian.tga")); + put("textures/entity/zombie_villager2/professions/nitwit.png", new TgaMapping("textures/entity/zombie_villager2/professions/nitwit.tga")); + put("textures/entity/zombie_villager2/professions/shepherd.png", new TgaMapping("textures/entity/zombie_villager2/professions/shepherd.tga")); + put("textures/entity/zombie_villager2/professions/stonemason.png", new TgaMapping("textures/entity/zombie_villager2/professions/stonemason.tga")); + put("textures/entity/zombie_villager2/professions/toolsmith.png", new TgaMapping("textures/entity/zombie_villager2/professions/toolsmith.tga")); + put("textures/entity/zombie_villager2/professions/weaponsmith.png", new TgaMapping("textures/entity/zombie_villager2/professions/weaponsmith.tga")); + put("textures/items/fireworks_charge.png", new TgaMapping("textures/items/fireworks_charge.tga")); + put("textures/items/leather_boots.png", new TgaMapping("textures/items/leather_boots.tga")); + put("textures/items/leather_helmet.png", new TgaMapping("textures/items/leather_helmet.tga")); + put("textures/items/leather_horse_armor.png", new TgaMapping("textures/items/leather_horse_armor.tga")); + put("textures/items/leather_leggings.png", new TgaMapping("textures/items/leather_leggings.tga")); + put("textures/models/armor/leather_1.png", new TgaMapping("textures/models/armor/leather_1.tga")); + put("textures/models/armor/leather_2.png", new TgaMapping("textures/models/armor/leather_2.tga")); + } + }; + + @Nullable + public static TgaMapping mapping(@NotNull String key) { + return MAPPINGS.get(key); + } + + record TgaMapping(String value, boolean keep) { + + public TgaMapping(String value) { + this(value, false); + } + } +} diff --git a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/TextureConverter.java b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/TextureConverter.java index 4f559d3..7c1ff60 100644 --- a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/TextureConverter.java +++ b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/TextureConverter.java @@ -100,21 +100,39 @@ public class TextureConverter implements Converter { Files.createDirectories(textureOutput.getParent()); } - try (OutputStream stream = Files.newOutputStream(textureOutput)) { - byte[] bytes = texture.data().toByteArray(); + byte[] bytes = texture.data().toByteArray(); - BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes)); - if (!image.getColorModel().hasAlpha()) { - BufferedImage newImage = new BufferedImage( - image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); + BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes)); - Graphics2D g = newImage.createGraphics(); - g.drawImage(image, 0, 0, null); - g.dispose(); - - image = newImage; + String pngKey = "textures/" + texture.key().value(); + PngToTgaMappings.TgaMapping mapping = PngToTgaMappings.mapping(pngKey); + if (mapping != null) { + Path tgaPath = context.outputDirectory().resolve(mapping.value()); + if (Files.notExists(tgaPath.getParent())) { + Files.createDirectories(tgaPath.getParent()); } + try (OutputStream tgaStream = Files.newOutputStream(tgaPath)) { + ImageIO.write(image, "tga", tgaStream); + if (!mapping.keep()) { + Files.deleteIfExists(textureOutput); + continue; + } + } + } + + if (!image.getColorModel().hasAlpha()) { + BufferedImage newImage = new BufferedImage( + image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); + + Graphics2D g = newImage.createGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + + image = newImage; + } + + try (OutputStream stream = Files.newOutputStream(textureOutput)) { ImageIO.write(image, "png", stream); } diff --git a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/ColorizeTransformer.java b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/ColorizeTransformer.java index 6fb6363..3640021 100644 --- a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/ColorizeTransformer.java +++ b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/ColorizeTransformer.java @@ -260,7 +260,7 @@ public class ColorizeTransformer implements BulkTextureTransformer { Key key = Key.key(Key.MINECRAFT_NAMESPACE, overlayPath); Texture texture = deleteOverlay ? context.poll(key) : context.peek(key); if (texture == null) { - context.warn("Missing overlay texture: " + overlayPath); + context.info("Missing overlay texture: " + overlayPath); continue; } diff --git a/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/OverlayTransformer.java b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/OverlayTransformer.java new file mode 100644 index 0000000..92ab72d --- /dev/null +++ b/converter/src/main/java/org/geysermc/pack/converter/converter/texture/transformer/bulk/type/OverlayTransformer.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/PackConverter + * + */ + +package org.geysermc.pack.converter.converter.texture.transformer.bulk.type; + +import com.google.auto.service.AutoService; +import net.kyori.adventure.key.Key; +import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTextureTransformer; +import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTransformContext; +import org.geysermc.pack.converter.util.ImageUtil; +import org.jetbrains.annotations.NotNull; +import team.unnamed.creative.texture.Texture; + +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.List; + +@AutoService(BulkTextureTransformer.class) +public class OverlayTransformer implements BulkTextureTransformer { + private static final List OVERLAYS = List.of( + // Cat + new OverlayData("entity/cat/cat_collar.png", "entity/cat/all_black.png", "entity/cat/allblackcat_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/british_shorthair.png", "entity/cat/britishshorthair_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/calico.png", "entity/cat/calico_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/jellie.png", "entity/cat/jellie_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/ocelot.png", "entity/cat/ocelot_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/persian.png", "entity/cat/persian_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/ragdoll.png", "entity/cat/ragdoll_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/red.png", "entity/cat/redtabby_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/siamese.png", "entity/cat/siamesecat_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/tabby.png", "entity/cat/tabby_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/black.png", "entity/cat/tuxedo_tame.png", false, true), + new OverlayData("entity/cat/cat_collar.png", "entity/cat/white.png", "entity/cat/white_tame.png", false, true), + + // Enderman + new OverlayData("entity/enderman/enderman.png", "entity/enderman/enderman_eyes.png", "entity/enderman/enderman.png", true), + + // Firework + new OverlayData("item/firework_star_overlay.png", "item/firework_star.png", "items/fireworks_charge.png", false), + + // Grass + new OverlayData("block/grass_block_side_overlay.png", "block/grass_block_side.png", "blocks/grass_side.png", false, true), + + // Leather + new OverlayData("item/leather_boots.png", "item/leather_boots_overlay.png", "items/leather_boots.png", true), + new OverlayData("item/leather_chestplate.png", "item/leather_chestplate_overlay.png", "items/leather_chestplate.png", true), + new OverlayData("item/leather_helmet.png", "item/leather_helmet_overlay.png", "items/leather_helmet.png", true), + new OverlayData("item/leather_leggings.png", "item/leather_leggings_overlay.png", "items/leather_leggings.png", true), + new OverlayData("models/armor/leather_layer_1.png", "models/armor/leather_layer_1_overlay.png", "models/armor/leather_1.png", true), + new OverlayData("models/armor/leather_layer_2.png", "models/armor/leather_layer_2_overlay.png", "models/armor/leather_2.png", true), + + // Phantom + new OverlayData("entity/phantom.png", "entity/phantom_eyes.png", "entity/phantom.png", true), + + // Spider + new OverlayData("entity/spider/cave_spider.png", "entity/spider_eyes.png", "entity/spider/cave_spider.png", true, true), + new OverlayData("entity/spider/spider.png", "entity/spider_eyes.png", "entity/spider/spider.png", true), + + // Wolf + new OverlayData("entity/wolf/wolf_collar.png", "entity/wolf/wolf_tame.png", "entity/wolf/wolf_tame.png", false, true) + ); + + @Override + public void transform(@NotNull BulkTransformContext context) throws IOException { + for (OverlayData overlay : OVERLAYS) { + String javaName = overlay.javaName(); + String overlayName = overlay.overlay(); + String bedrockName = overlay.bedrockName(); + boolean reverse = overlay.reverse(); + boolean keep = overlay.keep(); + + Texture texture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, javaName)); + if (texture == null) { + context.info(String.format("Base overlay texture %s not found", javaName)); + continue; + } + + Texture overlayTexture = keep ? context.peek(Key.key(Key.MINECRAFT_NAMESPACE, overlayName)) : context.poll(Key.key(Key.MINECRAFT_NAMESPACE, overlayName)); + if (overlayTexture == null) { + context.info(String.format("Overlay texture %s not found", overlayName)); + continue; + } + + context.info(String.format("Overlaying %s and %s onto %s", overlayName, javaName, bedrockName)); + + BufferedImage image = ImageIO.read(new ByteArrayInputStream(texture.data().toByteArray())); + BufferedImage imageOverlay = ImageIO.read(new ByteArrayInputStream(overlayTexture.data().toByteArray())); + + for (int x = 0; x < image.getWidth(); x++) { + for (int y = 0; y < image.getHeight(); y++) { + Color c = new Color(image.getRGB(x, y), true); + if (reverse ? c.getAlpha() > 0 : c.getAlpha() < 255) { + Color newCol = new Color(imageOverlay.getRGB(x, y), true); + newCol = new Color(newCol.getRed(), newCol.getGreen(), newCol.getBlue(), 2); + + image.setRGB(x, y, ImageUtil.colorToARGB(newCol)); + } + } + } + + context.offer(Key.key(Key.MINECRAFT_NAMESPACE, bedrockName), image, "png"); + } + } + + record OverlayData(@NotNull String javaName, @NotNull String overlay, @NotNull String bedrockName, boolean reverse, boolean keep) { + + public OverlayData(@NotNull String javaName, @NotNull String overlay, @NotNull String bedrockName, boolean reverse) { + this(javaName, overlay, bedrockName, reverse, false); + } + } +} diff --git a/converter/src/main/resources/mappings/textures.json b/converter/src/main/resources/mappings/textures.json index 6582e3c..9aed071 100644 --- a/converter/src/main/resources/mappings/textures.json +++ b/converter/src/main/resources/mappings/textures.json @@ -132,7 +132,8 @@ "yellow_glazed_terracotta": "glazed_terracotta_yellow", "grass_block_snow": "grass_side_snowed", "grass": "tallgrass", - "grass_block_side": "grass_side", + "grass_block_side": "grass_side_carried", + "grass_block_side_overlay": "grass_side", "grass_block_top": "grass_top", "terracotta": "hardened_clay", "black_terracotta": "hardened_clay_stained_black", diff --git a/legacy/OverlayToTranslateConverter.java b/legacy/OverlayToTranslateConverter.java deleted file mode 100644 index 65704c8..0000000 --- a/legacy/OverlayToTranslateConverter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/PackConverter - * - */ - -package org.geysermc.packconverter.converters; - -import com.google.auto.service.AutoService; -import lombok.Getter; -import org.geysermc.packconverter.PackConversionContext; -import org.geysermc.packconverter.PackConverter; -import org.geysermc.packconverter.utils.ImageUtils; -import org.jetbrains.annotations.NotNull; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -@AutoService(Converter.class) -public class OverlayToTranslateConverter extends AbstractConverter { - - @Getter - public static final List defaultData = new ArrayList<>(); - - static { - // Cat - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/allblackcat.png", "textures/entity/cat/allblackcat_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/britishshorthair.png", "textures/entity/cat/britishshorthair_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/calico.png", "textures/entity/cat/calico_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/jellie.png", "textures/entity/cat/jellie_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/ocelot.png", "textures/entity/cat/ocelot_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/persian.png", "textures/entity/cat/persian_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/ragdoll.png", "textures/entity/cat/ragdoll_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/redtabby.png", "textures/entity/cat/redtabby_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/siamesecat.png", "textures/entity/cat/siamesecat_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/tabby.png", "textures/entity/cat/tabby_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/tuxedo.png", "textures/entity/cat/tuxedo_tame.png", false, true}); - defaultData.add(new Object[] {"textures/entity/cat/graytabby_tame.png", "textures/entity/cat/white.png", "textures/entity/cat/white_tame.png", false, true}); - - // Enderman - defaultData.add(new Object[] {"textures/entity/enderman/enderman.png", "textures/entity/enderman/enderman_eyes.png", "textures/entity/enderman/enderman.png", true}); - - // Firework - defaultData.add(new Object[] {"textures/items/fireworks_charge.png", "textures/items/firework_star.png", "textures/items/fireworks_charge.png", false}); - - // Grass - defaultData.add(new Object[] {"textures/blocks/grass_side.png", "textures/blocks/grass_side_carried.png", "textures/blocks/grass_side.png", false, true}); - - // Leather - defaultData.add(new Object[] {"textures/items/leather_boots.png", "textures/items/leather_boots_overlay.png", "textures/items/leather_boots.png", true}); - defaultData.add(new Object[] {"textures/items/leather_chestplate.png", "textures/items/leather_chestplate_overlay.png", "textures/items/leather_chestplate.png", true}); - defaultData.add(new Object[] {"textures/items/leather_helmet.png", "textures/items/leather_helmet_overlay.png", "textures/items/leather_helmet.png", true}); - defaultData.add(new Object[] {"textures/items/leather_leggings.png", "textures/items/leather_leggings_overlay.png", "textures/items/leather_leggings.png", true}); - defaultData.add(new Object[] {"textures/models/armor/leather_1.png", "textures/models/armor/leather_1_overlay.png", "textures/models/armor/leather_1.png", true}); - defaultData.add(new Object[] {"textures/models/armor/leather_2.png", "textures/models/armor/leather_2_overlay.png", "textures/models/armor/leather_2.png", true}); - - // Phantom - defaultData.add(new Object[] {"textures/entity/phantom.png", "textures/entity/phantom_eyes.png", "textures/entity/phantom.png", true}); - - // Spider - defaultData.add(new Object[] {"textures/entity/spider/cave_spider.png", "textures/entity/spider_eyes.png", "textures/entity/spider/cave_spider.png", true, true}); - defaultData.add(new Object[] {"textures/entity/spider/spider.png", "textures/entity/spider_eyes.png", "textures/entity/spider/spider.png", true}); - - // Wolf - defaultData.add(new Object[] {"textures/entity/wolf/wolf_collar.png", "textures/entity/wolf/wolf_tame.png", "textures/entity/wolf/wolf_tame.png", false, true}); - } - - public OverlayToTranslateConverter(PackConverter packConverter, Path storage, Object[] data) { - super(packConverter, storage, data); - } - - @Override - public List convert(@NotNull PackConversionContext context) { - List delete = new ArrayList<>(); - - try { - String from = (String) context.data()[0]; - String overlay = (String) context.data()[1]; - String to = (String) context.data()[2]; - boolean reverse = (boolean) context.data()[3]; - boolean dontDelete = context.data().length > 4 && (boolean) context.data()[4]; - - File fromFile = storage.resolve(from).toFile(); - File overlayFile = storage.resolve(overlay).toFile(); - - if (!fromFile.exists() || !overlayFile.exists()) { - return delete; - } - - context.log(String.format("Create translated overlay %s", to)); - - BufferedImage image = ImageIO.read(fromFile); - BufferedImage imageOverlay = ImageIO.read(overlayFile); - - for (int x = 0; x < image.getWidth(); x++) { - for (int y = 0; y < image.getHeight(); y++) { - Color c = new Color(image.getRGB(x, y), true); - if (reverse ? c.getAlpha() > 0 : c.getAlpha() < 255) { - Color newCol = new Color(imageOverlay.getRGB(x, y), true); - newCol = new Color(newCol.getRed(), newCol.getGreen(), newCol.getBlue(), 2); - - image.setRGB(x, y, ImageUtils.colorToARGB(newCol)); - } - } - } - - ImageUtils.write(image, "png", storage.resolve(to).toFile()); - - if (!dontDelete) { - delete.add(new DeleteConverter(packConverter, storage, new Object[] {overlay})); - } - } catch (IOException e) { } - - return delete; - } -}