diff --git a/patches/minecraft/net/minecraft/entity/passive/EntityHorse.java.patch b/patches/minecraft/net/minecraft/entity/passive/EntityHorse.java.patch new file mode 100644 index 0000000000..fdce8b1f5f --- /dev/null +++ b/patches/minecraft/net/minecraft/entity/passive/EntityHorse.java.patch @@ -0,0 +1,80 @@ +--- ../src-base/minecraft/net/minecraft/entity/passive/EntityHorse.java ++++ ../src-work/minecraft/net/minecraft/entity/passive/EntityHorse.java +@@ -34,6 +34,7 @@ + private static final UUID field_184786_bD = UUID.fromString("556E1665-8B10-40C8-8F9D-CF9B1667F295"); + private static final DataParameter field_184789_bG = EntityDataManager.func_187226_a(EntityHorse.class, DataSerializers.field_187192_b); + private static final DataParameter field_184791_bI = EntityDataManager.func_187226_a(EntityHorse.class, DataSerializers.field_187192_b); ++ private static final DataParameter HORSE_ARMOR_STACK = EntityDataManager.func_187226_a(EntityHorse.class, DataSerializers.field_187196_f); + private static final String[] field_110268_bz = new String[] {"textures/entity/horse/horse_white.png", "textures/entity/horse/horse_creamy.png", "textures/entity/horse/horse_chestnut.png", "textures/entity/horse/horse_brown.png", "textures/entity/horse/horse_black.png", "textures/entity/horse/horse_gray.png", "textures/entity/horse/horse_darkbrown.png"}; + private static final String[] field_110269_bA = new String[] {"hwh", "hcr", "hch", "hbr", "hbl", "hgr", "hdb"}; + private static final String[] field_110291_bB = new String[] {null, "textures/entity/horse/horse_markings_white.png", "textures/entity/horse/horse_markings_whitefield.png", "textures/entity/horse/horse_markings_whitedots.png", "textures/entity/horse/horse_markings_blackdots.png"}; +@@ -51,6 +52,7 @@ + super.func_70088_a(); + this.field_70180_af.func_187214_a(field_184789_bG, Integer.valueOf(0)); + this.field_70180_af.func_187214_a(field_184791_bI, Integer.valueOf(HorseArmorType.NONE.func_188579_a())); ++ this.field_70180_af.func_187214_a(HORSE_ARMOR_STACK, ItemStack.field_190927_a); + } + + public static void func_189803_b(DataFixer p_189803_0_) +@@ -79,7 +81,7 @@ + { + ItemStack itemstack = new ItemStack(p_70037_1_.func_74775_l("ArmorItem")); + +- if (!itemstack.func_190926_b() && HorseArmorType.func_188577_b(itemstack.func_77973_b())) ++ if (!itemstack.func_190926_b() && func_190682_f(itemstack)) + { + this.field_110296_bG.func_70299_a(1, itemstack); + } +@@ -110,11 +112,12 @@ + int i = this.func_110202_bQ(); + int j = (i & 255) % 7; + int k = ((i & 65280) >> 8) % 5; +- HorseArmorType horsearmortype = this.func_184783_dl(); ++ ItemStack armorStack = this.field_70180_af.func_187225_a(HORSE_ARMOR_STACK); ++ String texture = !armorStack.func_190926_b() ? armorStack.func_77973_b().getHorseArmorTexture(this, armorStack) : HorseArmorType.func_188575_a(this.field_70180_af.func_187225_a(field_184791_bI)).func_188574_d(); //If armorStack is empty, the server is vanilla so the texture should be determined the vanilla way + this.field_110280_bR[0] = field_110268_bz[j]; + this.field_110280_bR[1] = field_110291_bB[k]; +- this.field_110280_bR[2] = horsearmortype.func_188574_d(); +- this.field_110286_bQ = "horse/" + field_110269_bA[j] + field_110292_bC[k] + horsearmortype.func_188573_b(); ++ this.field_110280_bR[2] = texture; ++ this.field_110286_bQ = "horse/" + field_110269_bA[j] + field_110292_bC[k] + texture; + } + + @SideOnly(Side.CLIENT) +@@ -149,6 +152,7 @@ + { + HorseArmorType horsearmortype = HorseArmorType.func_188580_a(p_146086_1_); + this.field_70180_af.func_187227_b(field_184791_bI, Integer.valueOf(horsearmortype.func_188579_a())); ++ this.field_70180_af.func_187227_b(HORSE_ARMOR_STACK, p_146086_1_); + this.func_110230_cF(); + + if (!this.field_70170_p.field_72995_K) +@@ -165,7 +169,9 @@ + + public HorseArmorType func_184783_dl() + { +- return HorseArmorType.func_188575_a(((Integer)this.field_70180_af.func_187225_a(field_184791_bI)).intValue()); ++ HorseArmorType armor = HorseArmorType.func_188580_a(this.field_70180_af.func_187225_a(HORSE_ARMOR_STACK)); //First check the Forge armor DataParameter ++ if (armor == HorseArmorType.NONE) armor = HorseArmorType.func_188575_a(this.field_70180_af.func_187225_a(field_184791_bI)); //If the Forge armor DataParameter returns NONE, fallback to the vanilla armor DataParameter. This is necessary to prevent issues with Forge clients connected to vanilla servers. ++ return armor; + } + + public void func_76316_a(IInventory p_76316_1_) +@@ -207,6 +213,8 @@ + this.field_70180_af.func_187230_e(); + this.func_110230_cF(); + } ++ ItemStack armor = this.field_110296_bG.func_70301_a(1); ++ if (func_190682_f(armor)) armor.func_77973_b().onHorseArmorTick(field_70170_p, this, armor); + } + + protected SoundEvent func_184639_G() +@@ -381,7 +389,7 @@ + + public boolean func_190682_f(ItemStack p_190682_1_) + { +- return HorseArmorType.func_188577_b(p_190682_1_.func_77973_b()); ++ return HorseArmorType.isHorseArmor(p_190682_1_); + } + + @Nullable diff --git a/patches/minecraft/net/minecraft/entity/passive/HorseArmorType.java.patch b/patches/minecraft/net/minecraft/entity/passive/HorseArmorType.java.patch new file mode 100644 index 0000000000..31bd698ae0 --- /dev/null +++ b/patches/minecraft/net/minecraft/entity/passive/HorseArmorType.java.patch @@ -0,0 +1,53 @@ +--- ../src-base/minecraft/net/minecraft/entity/passive/HorseArmorType.java ++++ ../src-work/minecraft/net/minecraft/entity/passive/HorseArmorType.java +@@ -55,6 +55,7 @@ + return this.field_188586_e; + } + ++ @Deprecated /**Forge: Use getByName. Ordinals of mod-added enum constants are dependent on load order, unlike names.**/ + public static HorseArmorType func_188575_a(int p_188575_0_) + { + return values()[p_188575_0_]; +@@ -62,9 +63,10 @@ + + public static HorseArmorType func_188580_a(ItemStack p_188580_0_) + { +- return p_188580_0_.func_190926_b() ? NONE : func_188576_a(p_188580_0_.func_77973_b()); ++ return p_188580_0_.func_77973_b().getHorseArmorType(p_188580_0_); + } + ++ @Deprecated //Forge: Use getByItemStack + public static HorseArmorType func_188576_a(Item p_188576_0_) + { + if (p_188576_0_ == Items.field_151138_bX) +@@ -81,8 +83,30 @@ + } + } + ++ @Deprecated //Forge: Use ItemStack sensitive overload + public static boolean func_188577_b(Item p_188577_0_) + { + return func_188576_a(p_188577_0_) != NONE; + } ++ ++ /* ======================================== FORGE START ======================================== */ ++ //Allows for textures located outside the vanilla horse armor folder ++ private HorseArmorType(String defaultTextureLocation, int armorStrengthIn) ++ { ++ this.field_188588_g = armorStrengthIn; ++ this.field_188586_e = defaultTextureLocation; ++ this.field_188587_f = "forge"; ++ } ++ ++ public static HorseArmorType getByName(String name) ++ { ++ HorseArmorType type = HorseArmorType.valueOf(name); ++ return type != null ? type : NONE; ++ } ++ ++ public static boolean isHorseArmor(ItemStack stack) ++ { ++ return func_188580_a(stack) != NONE; ++ } ++ /* ======================================== FORGE END ======================================== */ + } diff --git a/patches/minecraft/net/minecraft/item/Item.java.patch b/patches/minecraft/net/minecraft/item/Item.java.patch index b891ac477d..c5da7368c9 100644 --- a/patches/minecraft/net/minecraft/item/Item.java.patch +++ b/patches/minecraft/net/minecraft/item/Item.java.patch @@ -68,7 +68,7 @@ CreativeTabs creativetabs = this.func_77640_w(); return creativetabs != null && (p_194125_1_ == CreativeTabs.field_78027_g || p_194125_1_ == creativetabs); } -@@ -435,11 +441,704 @@ +@@ -435,11 +441,728 @@ return false; } @@ -767,13 +767,37 @@ + { + return -1; + } ++ ++ /** ++ * Returns an enum constant of type {@code HorseArmorType}. ++ * The returned enum constant will be used to determine the armor value and texture of this item when equipped. ++ * @param stack the armor stack ++ * @return an enum constant of type {@code HorseArmorType}. Return HorseArmorType.NONE if this is not horse armor ++ */ ++ public net.minecraft.entity.passive.HorseArmorType getHorseArmorType(ItemStack stack) ++ { ++ return net.minecraft.entity.passive.HorseArmorType.func_188576_a(stack.func_77973_b()); ++ } ++ ++ public String getHorseArmorTexture(net.minecraft.entity.EntityLiving wearer, ItemStack stack) ++ { ++ return getHorseArmorType(stack).func_188574_d(); ++ } ++ ++ /** ++ * Called every tick from {@link EntityHorse#onUpdate()} on the item in the armor slot. ++ * @param world the world the horse is in ++ * @param horse the horse wearing this armor ++ * @param armor the armor itemstack ++ */ ++ public void onHorseArmorTick(World world, net.minecraft.entity.EntityLiving horse, ItemStack armor) {} + + /* ======================================== FORGE END =====================================*/ + public static void func_150900_l() { func_179214_a(Blocks.field_150350_a, new ItemAir(Blocks.field_150350_a)); -@@ -999,6 +1698,8 @@ +@@ -999,6 +1722,8 @@ private final float field_78010_h; private final float field_78011_i; private final int field_78008_j; @@ -782,7 +806,7 @@ private ToolMaterial(int p_i1874_3_, int p_i1874_4_, float p_i1874_5_, float p_i1874_6_, int p_i1874_7_) { -@@ -1034,6 +1735,7 @@ +@@ -1034,6 +1759,7 @@ return this.field_78008_j; } @@ -790,7 +814,7 @@ public Item func_150995_f() { if (this == WOOD) -@@ -1057,5 +1759,21 @@ +@@ -1057,5 +1783,21 @@ return this == DIAMOND ? Items.field_151045_i : null; } } diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 950b01fbd4..81f7fb25c8 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -75,6 +75,8 @@ import net.minecraft.client.resources.I18n; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.passive.EntityHorse; +import net.minecraft.entity.passive.HorseArmorType; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; @@ -754,4 +756,11 @@ public class ForgeHooksClient { MinecraftForge.EVENT_BUS.post(new InputUpdateEvent(player, movementInput)); } + + public static String getHorseArmorTexture(EntityHorse horse, ItemStack armorStack) + { + String texture = armorStack.getItem().getHorseArmorTexture(horse, armorStack); + if(texture == null) texture = horse.getHorseArmorType().getTextureName(); + return texture; + } } diff --git a/src/main/java/net/minecraftforge/common/util/EnumHelper.java b/src/main/java/net/minecraftforge/common/util/EnumHelper.java index 8feec72f9f..8fcc9c57db 100644 --- a/src/main/java/net/minecraftforge/common/util/EnumHelper.java +++ b/src/main/java/net/minecraftforge/common/util/EnumHelper.java @@ -34,6 +34,7 @@ import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityPainting.EnumArt; +import net.minecraft.entity.passive.HorseArmorType; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; @@ -74,7 +75,8 @@ public class EnumHelper {EnumSkyBlock.class, int.class}, {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, - {EnumRarity.class, TextFormatting.class, String.class} + {EnumRarity.class, TextFormatting.class, String.class}, + {HorseArmorType.class, String.class, int.class} }; @Nullable @@ -143,6 +145,19 @@ public class EnumHelper return addEnum(EnumRarity.class, name, color, displayName); } + /** + * + * @param name the name of the new {@code HorseArmorType} + * @param textureLocation the path to the texture for this armor type. It must follow the format domain:path and be relative to the assets folder. + * @param armorStrength how much protection this armor type should give + * @return the new {@code HorseArmorType}, or null if it could not be created + */ + @Nullable + public static HorseArmorType addHorseArmor(String name, String textureLocation, int armorStrength) + { + return addEnum(HorseArmorType.class, name, textureLocation, armorStrength); + } + private static void setup() { if (isSetup) diff --git a/src/test/java/net/minecraftforge/debug/HorseArmorTest.java b/src/test/java/net/minecraftforge/debug/HorseArmorTest.java new file mode 100644 index 0000000000..94d498865d --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/HorseArmorTest.java @@ -0,0 +1,80 @@ +package net.minecraftforge.debug; + +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.passive.HorseArmorType; +import net.minecraft.init.MobEffects; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionEffect; +import net.minecraft.world.World; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; +import net.minecraftforge.fml.relauncher.Side; + +@EventBusSubscriber +@Mod(modid = HorseArmorTest.MODID, name = "HorseArmorTest", version = "1.0", acceptableRemoteVersions = "*") +public class HorseArmorTest +{ + public static final String MODID = "horse_armor_test"; + public static final boolean ENABLED = true; + + public static HorseArmorType testArmorType; + @ObjectHolder("test_armor") + public static final ItemTestHorseArmor TEST_ARMOR = null; + + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) + { + if(ENABLED) + testArmorType = EnumHelper.addHorseArmor("test", MODID + ":textures/entity/horse/armor/test.png", 15); + } + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) + { + if(ENABLED) + event.getRegistry().register(new ItemTestHorseArmor().setRegistryName(MODID, "test_armor").setUnlocalizedName(MODID + ".testArmor")); + } + + @EventBusSubscriber(modid = MODID, value = Side.CLIENT) + public static class ClientEventHandler + { + @SubscribeEvent + public static void registerModels(ModelRegistryEvent event) + { + if(ENABLED) + ModelLoader.setCustomModelResourceLocation(TEST_ARMOR, 0, new ModelResourceLocation(TEST_ARMOR.getRegistryName(), "inventory")); + } + } + + private static class ItemTestHorseArmor extends Item + { + @Override + public HorseArmorType getHorseArmorType(ItemStack stack) + { + return testArmorType; + } + + @Override + public String getHorseArmorTexture(EntityLiving wearer, ItemStack stack) + { + return stack.isItemEnchanted() ? HorseArmorType.IRON.getTextureName() : super.getHorseArmorTexture(wearer, stack); + } + + @Override + public void onHorseArmorTick(World world, EntityLiving wearer, ItemStack itemStack) + { + if(wearer.ticksExisted % 15 == 0) + wearer.addPotionEffect(new PotionEffect(MobEffects.GLOWING, 20, 1)); + } + } +} diff --git a/src/test/java/net/minecraftforge/test/EnumHelperTest.java b/src/test/java/net/minecraftforge/test/EnumHelperTest.java index b0dc459837..159448e467 100644 --- a/src/test/java/net/minecraftforge/test/EnumHelperTest.java +++ b/src/test/java/net/minecraftforge/test/EnumHelperTest.java @@ -3,6 +3,7 @@ package net.minecraftforge.test; import com.google.common.base.Joiner; import com.google.common.base.Throwables; import net.minecraft.enchantment.EnumEnchantmentType; +import net.minecraft.entity.passive.HorseArmorType; import net.minecraft.init.Bootstrap; import net.minecraftforge.client.EnumHelperClient; import net.minecraftforge.common.BiomeDictionary; @@ -90,6 +91,10 @@ public class EnumHelperTest { filter = true; //We don't want people using this method. } + if (returnType == HorseArmorType.class && (declaredConstructor.getParameterTypes().length == 3 || declaredConstructor.getParameterTypes()[2] == int.class)) + { + filter = true; //We don't want people using either of these methods. + } if (!filter) { diff --git a/src/test/resources/assets/horse_armor_test/lang/en_US.lang b/src/test/resources/assets/horse_armor_test/lang/en_US.lang new file mode 100644 index 0000000000..a316b4a1b5 --- /dev/null +++ b/src/test/resources/assets/horse_armor_test/lang/en_US.lang @@ -0,0 +1 @@ +item.horse_armor_test.testArmor.name=Test Armor \ No newline at end of file diff --git a/src/test/resources/assets/horse_armor_test/models/item/test_armor.json b/src/test/resources/assets/horse_armor_test/models/item/test_armor.json new file mode 100644 index 0000000000..63893464a0 --- /dev/null +++ b/src/test/resources/assets/horse_armor_test/models/item/test_armor.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "horse_armor_test:items/test_armor" + } +} \ No newline at end of file diff --git a/src/test/resources/assets/horse_armor_test/textures/entity/horse/armor/test.png b/src/test/resources/assets/horse_armor_test/textures/entity/horse/armor/test.png new file mode 100644 index 0000000000..fac063d109 Binary files /dev/null and b/src/test/resources/assets/horse_armor_test/textures/entity/horse/armor/test.png differ diff --git a/src/test/resources/assets/horse_armor_test/textures/items/test_armor.png b/src/test/resources/assets/horse_armor_test/textures/items/test_armor.png new file mode 100644 index 0000000000..d59d38935b Binary files /dev/null and b/src/test/resources/assets/horse_armor_test/textures/items/test_armor.png differ