From f2b54acd67a3530942c351d4dff68539b211193e Mon Sep 17 00:00:00 2001 From: XCompWiz Date: Fri, 11 Jan 2019 18:22:32 -0500 Subject: [PATCH] Allow providing a BufferedImage for banner render generation (#5041) Ported to 1.13 using NativeImage Co-authored-by: tterrag --- .../LayeredColorMaskTexture.java.patch | 12 ++ .../client/MinecraftForgeClient.java | 26 +++ .../debug/gameplay/DynamicBannerTest.java | 184 ++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 patches/minecraft/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java.patch create mode 100644 src/test/java/net/minecraftforge/debug/gameplay/DynamicBannerTest.java diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java.patch b/patches/minecraft/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java.patch new file mode 100644 index 0000000000..55d8503cd3 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java ++++ b/net/minecraft/client/renderer/texture/LayeredColorMaskTexture.java +@@ -38,8 +38,7 @@ + String s = this.field_174949_h.get(i); + if (s != null) { + try ( +- IResource iresource1 = p_195413_1_.func_199002_a(new ResourceLocation(s)); +- NativeImage nativeimage2 = NativeImage.func_195713_a(iresource1.func_199027_b()); ++ NativeImage nativeimage2 = net.minecraftforge.client.MinecraftForgeClient.getImageLayer(new ResourceLocation(s), p_195413_1_); + ) { + int j = ((EnumDyeColor)this.field_174950_i.get(i)).func_196057_c(); + if (nativeimage2.func_195702_a() == nativeimage1.func_195702_a() && nativeimage2.func_195714_b() == nativeimage1.func_195714_b()) { diff --git a/src/main/java/net/minecraftforge/client/MinecraftForgeClient.java b/src/main/java/net/minecraftforge/client/MinecraftForgeClient.java index 65ee3f9dcf..9f171d817f 100644 --- a/src/main/java/net/minecraftforge/client/MinecraftForgeClient.java +++ b/src/main/java/net/minecraftforge/client/MinecraftForgeClient.java @@ -19,12 +19,21 @@ package net.minecraftforge.client; +import java.io.IOException; import java.util.BitSet; +import java.util.HashMap; import java.util.Locale; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import javax.annotation.Nonnull; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.NativeImage; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkCache; import net.minecraft.world.World; @@ -124,4 +133,21 @@ public class MinecraftForgeClient regionCache.invalidateAll(); regionCache.cleanUp(); } + + private static HashMap> bufferedImageSuppliers = new HashMap>(); + public static void registerImageLayerSupplier(ResourceLocation resourceLocation, Supplier supplier) + { + bufferedImageSuppliers.put(resourceLocation, supplier); + } + + @Nonnull + public static NativeImage getImageLayer(ResourceLocation resourceLocation, IResourceManager resourceManager) throws IOException + { + Supplier supplier = bufferedImageSuppliers.get(resourceLocation); + if (supplier != null) + return supplier.get(); + + IResource iresource1 = resourceManager.getResource(resourceLocation); + return NativeImage.read(iresource1.getInputStream()); + } } diff --git a/src/test/java/net/minecraftforge/debug/gameplay/DynamicBannerTest.java b/src/test/java/net/minecraftforge/debug/gameplay/DynamicBannerTest.java new file mode 100644 index 0000000000..46fb546b02 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/gameplay/DynamicBannerTest.java @@ -0,0 +1,184 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.gameplay; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BannerTextures; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.ItemBanner; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.BannerPattern; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod(modid = DynamicBannerTest.MODID, name = "ForgeDebugDynamicBanner", version = DynamicBannerTest.VERSION, acceptableRemoteVersions = "*") +public class DynamicBannerTest +{ + private static final boolean ENABLE = false; + public static final String MODID = "forgedebugdynamicbanner"; + public static final String VERSION = "1.0"; + + public static CreativeTabs bannerTab; + @SidedProxy + public static CommonProxy proxy = null; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) + { + if (ENABLE) + { + BannerPattern pattern = addBasicPattern("Y"); + proxy.registerSupplier(new ResourceLocation("textures/entity/banner/" + pattern.getFileName() + ".png")); + proxy.registerSupplier(new ResourceLocation("textures/entity/shield/" + pattern.getFileName() + ".png")); + bannerTab = new CreativeTabBanners("dynbanner.banners"); + } + } + + public static abstract class CommonProxy + { + public void registerSupplier(ResourceLocation location) + { + } + } + + public static final class ServerProxy extends CommonProxy + { + } + + public static final class ClientProxy extends CommonProxy + { + @Override + @SideOnly(Side.CLIENT) + public void registerSupplier(ResourceLocation location) + { + MinecraftForgeClient.registerImageLayerSupplier(location, () -> { + return createBufferedImage(); + }); + } + } + + public static BannerPattern addBasicPattern(String name) + { + final Class[] paramTypes = { String.class, String.class }; + final Object[] paramValues = { MODID + "_" + name, MODID + "." + name }; + return EnumHelper.addEnum(BannerPattern.class, name.toUpperCase(), paramTypes, paramValues); + } + + @SideOnly(Side.CLIENT) + private static BufferedImage createBufferedImage() + { + BufferedImage baseImage = buildBackground(); + + int width = 11; + int height = 30; + int startX = 5; + int startY = 5; + + for (int xx = startX; xx <= startX + width; xx++) + { + for (int yy = startY; yy <= startY + height; yy++) + { + baseImage.setRGB(xx, yy, 0xFF000000); // Black + } + } + return baseImage; + } + + @SideOnly(Side.CLIENT) + private static BufferedImage buildBackground() + { + ResourceLocation originalBackground = BannerTextures.BANNER_BASE_TEXTURE; + try (InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(originalBackground).getInputStream()) + { + return ImageIO.read(is); + } + catch (IOException exc) + { + throw new RuntimeException("Couldn't find or open the page background image.", exc); + } + } + + public static NBTTagList makePatternNBTList(BannerPattern pattern, EnumDyeColor color) + { + final NBTTagList patterns = new NBTTagList(); + final NBTTagCompound tag = new NBTTagCompound(); + tag.setString("Pattern", pattern.getHashname()); + tag.setInteger("Color", color.getDyeDamage()); + patterns.appendTag(tag); + return patterns; + } + + public static class CreativeTabBanners extends CreativeTabs + { + private static ItemStack DISPLAY = null; + + public CreativeTabBanners(String id) + { + super(id); + this.setBackgroundImageName("item_search.png"); + } + + @Override + public ItemStack getTabIconItem() + { + return this.getIconItemStack(); + } + + @Override + public ItemStack getIconItemStack() + { + if (DISPLAY == null) + DISPLAY = ItemBanner.makeBanner(EnumDyeColor.WHITE, makePatternNBTList(BannerPattern.CREEPER, EnumDyeColor.GREEN)); + + return DISPLAY; + } + + @Override + public boolean hasSearchBar() + { + return true; + } + + @Override + public void displayAllRelevantItems(NonNullList itemList) + { + super.displayAllRelevantItems(itemList); + + for (final BannerPattern pattern : BannerPattern.values()) + itemList.add(ItemBanner.makeBanner(EnumDyeColor.WHITE, makePatternNBTList(pattern, EnumDyeColor.BLACK))); + } + } +}