diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/HumanoidArmorLayer.java.patch b/patches/minecraft/net/minecraft/client/renderer/entity/layers/HumanoidArmorLayer.java.patch new file mode 100644 index 00000000000..697450e0348 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/HumanoidArmorLayer.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/client/renderer/entity/layers/HumanoidArmorLayer.java ++++ b/net/minecraft/client/renderer/entity/layers/HumanoidArmorLayer.java +@@ -66,6 +_,7 @@ + if (armoritem.getEquipmentSlot() == p_117122_) { + this.getParentModel().copyPropertiesTo(p_117124_); + this.setPartVisibility(p_117124_, p_117122_); ++ net.minecraft.client.model.Model model = getArmorModelHook(p_117121_, itemstack, p_117122_, p_117124_); + boolean flag = this.usesInnerModel(p_117122_); + ArmorMaterial armormaterial = armoritem.getMaterial().value(); + int i = itemstack.is(ItemTags.DYEABLE) ? DyedItemColor.getOrDefault(itemstack, -6265536) : -1; +@@ -83,17 +_,17 @@ + f1 = 1.0F; + f2 = 1.0F; + } +- +- this.renderModel(p_117119_, p_117120_, p_117123_, p_117124_, f, f1, f2, armormaterial$layer.texture(flag)); ++ var texture = net.minecraftforge.client.ForgeHooksClient.getArmorTexture(p_117121_, itemstack, p_117122_, armormaterial$layer, flag); ++ this.renderModel(p_117119_, p_117120_, p_117123_, model, f, f1, f2, texture); + } + + ArmorTrim armortrim = itemstack.get(DataComponents.TRIM); + if (armortrim != null) { +- this.renderTrim(armoritem.getMaterial(), p_117119_, p_117120_, p_117123_, armortrim, p_117124_, flag); ++ this.renderTrim(armoritem.getMaterial(), p_117119_, p_117120_, p_117123_, armortrim, model, flag); + } + + if (itemstack.hasFoil()) { +- this.renderGlint(p_117119_, p_117120_, p_117123_, p_117124_); ++ this.renderGlint(p_117119_, p_117120_, p_117123_, model); + } + } + } +@@ -122,11 +_,15 @@ + } + } + ++ private void renderModel(PoseStack p_289664_, MultiBufferSource p_289689_, int p_289681_, A p_289658_, float p_289678_, float p_289674_, float p_289693_, ResourceLocation p_328978_) { ++ renderModel(p_289664_, p_289689_, p_289681_, (net.minecraft.client.model.Model)p_289658_, p_289678_, p_289674_, p_289693_, p_328978_); ++ } ++ + private void renderModel( + PoseStack p_289664_, + MultiBufferSource p_289689_, + int p_289681_, +- A p_289658_, ++ net.minecraft.client.model.Model p_289658_, + float p_289678_, + float p_289674_, + float p_289693_, +@@ -136,8 +_,12 @@ + p_289658_.renderToBuffer(p_289664_, vertexconsumer, p_289681_, OverlayTexture.NO_OVERLAY, p_289678_, p_289674_, p_289693_, 1.0F); + } + ++ private void renderTrim(Holder p_331988_, PoseStack p_289687_, MultiBufferSource p_289643_, int p_289683_, ArmorTrim p_289692_, A p_289663_, boolean p_289651_) { ++ renderTrim(p_331988_, p_289687_, p_289643_, p_289683_, p_289692_, (net.minecraft.client.model.Model)p_289663_, p_289651_); ++ } ++ + private void renderTrim( +- Holder p_331988_, PoseStack p_289687_, MultiBufferSource p_289643_, int p_289683_, ArmorTrim p_289692_, A p_289663_, boolean p_289651_ ++ Holder p_331988_, PoseStack p_289687_, MultiBufferSource p_289643_, int p_289683_, ArmorTrim p_289692_, net.minecraft.client.model.Model p_289663_, boolean p_289651_ + ) { + TextureAtlasSprite textureatlassprite = this.armorTrimAtlas.getSprite(p_289651_ ? p_289692_.innerTexture(p_331988_) : p_289692_.outerTexture(p_331988_)); + VertexConsumer vertexconsumer = textureatlassprite.wrap(p_289643_.getBuffer(Sheets.armorTrimsSheet(p_289692_.pattern().value().decal()))); +@@ -145,6 +_,10 @@ + } + + private void renderGlint(PoseStack p_289673_, MultiBufferSource p_289654_, int p_289649_, A p_289659_) { ++ renderGlint(p_289673_, p_289654_, p_289649_, (net.minecraft.client.model.Model)p_289659_); ++ } ++ ++ private void renderGlint(PoseStack p_289673_, MultiBufferSource p_289654_, int p_289649_, net.minecraft.client.model.Model p_289659_) { + p_289659_.renderToBuffer(p_289673_, p_289654_.getBuffer(RenderType.armorEntityGlint()), p_289649_, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); + } + +@@ -154,5 +_,12 @@ + + private boolean usesInnerModel(EquipmentSlot p_117129_) { + return p_117129_ == EquipmentSlot.LEGS; ++ } ++ ++ /** ++ * Hook to allow item-sensitive armor model. for HumanoidArmorLayer. ++ */ ++ protected net.minecraft.client.model.Model getArmorModelHook(T entity, ItemStack itemStack, EquipmentSlot slot, A model) { ++ return net.minecraftforge.client.ForgeHooksClient.getArmorModel(entity, itemStack, slot, model); + } + } diff --git a/patches/minecraft/net/minecraft/world/item/ArmorMaterial.java.patch b/patches/minecraft/net/minecraft/world/item/ArmorMaterial.java.patch new file mode 100644 index 00000000000..ee2a4546d31 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/item/ArmorMaterial.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/item/ArmorMaterial.java ++++ b/net/minecraft/world/item/ArmorMaterial.java +@@ -56,5 +_,9 @@ + public boolean dyeable() { + return this.dyeable; + } ++ ++ public String getSuffix() { ++ return this.suffix; ++ } + } + } diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index ec70520bea6..6ddb7c8c292 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -98,6 +98,7 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.ArmorMaterial; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeManager; @@ -260,9 +261,9 @@ public static void onClientPauseChangePost(boolean pause) { MinecraftForge.EVENT_BUS.post(new ClientPauseChangeEvent.Post(pause)); } - public static String getArmorTexture(Entity entity, ItemStack armor, String _default, EquipmentSlot slot, String type) { - String result = armor.getItem().getArmorTexture(armor, entity, slot, type); - return result != null ? result : _default; + public static ResourceLocation getArmorTexture(Entity entity, ItemStack armor, EquipmentSlot slot, ArmorMaterial.Layer layer, boolean inner) { + var result = armor.getItem().getArmorTexture(armor, entity, slot, layer, inner); + return result != null ? result : layer.texture(inner); } public static boolean onDrawHighlight(LevelRenderer context, Camera camera, HitResult target, float partialTick, Matrix4f ctxPos, MultiBufferSource bufferSource) { diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java b/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java index 38496f55997..30de58cd201 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java @@ -28,6 +28,7 @@ import net.minecraft.world.InteractionResult; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ToolAction; @@ -326,11 +327,12 @@ default boolean isBookEnchantable(ItemStack stack, ItemStack book) { * @param stack ItemStack for the equipped armor * @param entity The entity wearing the armor * @param slot The slot the armor is in - * @param type The subtype, can be null or "overlay" + * @param layer The layer of the armor being rendered. Typically want to use {@alin ArmorMaterial.Layer#getSuffix()}. + * @param inner Weither or not to use the inner texture layer. * @return Path of texture to bind, or null to use default */ @Nullable - default String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { + default ResourceLocation getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, ArmorMaterial.Layer layer, boolean inner) { return null; }