diff --git a/patches/minecraft/net/minecraft/entity/EntityLiving.java.patch b/patches/minecraft/net/minecraft/entity/EntityLiving.java.patch index 78f792a1b..d23ec224a 100644 --- a/patches/minecraft/net/minecraft/entity/EntityLiving.java.patch +++ b/patches/minecraft/net/minecraft/entity/EntityLiving.java.patch @@ -66,3 +66,23 @@ } } else +@@ -1434,5 +1448,19 @@ + ON_GROUND, + IN_AIR, + IN_WATER; ++ ++ private final java.util.function.BiPredicate spawnPredicate; ++ ++ SpawnPlacementType() { this.spawnPredicate = null; } ++ ++ SpawnPlacementType(java.util.function.BiPredicate spawnPredicate) ++ { ++ this.spawnPredicate = spawnPredicate; ++ } ++ ++ public boolean canSpawnAt(World world, BlockPos pos) ++ { ++ return this.spawnPredicate != null ? this.spawnPredicate.test(world, pos) : net.minecraft.world.WorldEntitySpawner.canCreatureTypeSpawnBody(this, world, pos); ++ } + } + } diff --git a/patches/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java.patch b/patches/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java.patch index b21656f61..daaee1873 100644 --- a/patches/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java.patch +++ b/patches/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java.patch @@ -1,13 +1,16 @@ --- ../src-base/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java +++ ../src-work/minecraft/net/minecraft/entity/EntitySpawnPlacementRegistry.java -@@ -53,6 +53,12 @@ - return field_180110_a.get(p_180109_0_); +@@ -50,9 +50,14 @@ + + public static EntityLiving.SpawnPlacementType func_180109_a(Class p_180109_0_) + { +- return field_180110_a.get(p_180109_0_); ++ return field_180110_a.getOrDefault(p_180109_0_, EntityLiving.SpawnPlacementType.ON_GROUND); } + public static void setPlacementType(Class entityClass, EntityLiving.SpawnPlacementType placementType) + { -+ if(!field_180110_a.containsKey(entityClass)) -+ field_180110_a.put(entityClass, placementType); ++ field_180110_a.putIfAbsent(entityClass, placementType); + } + static diff --git a/patches/minecraft/net/minecraft/world/WorldEntitySpawner.java.patch b/patches/minecraft/net/minecraft/world/WorldEntitySpawner.java.patch index 1ed609ccf..fa334277d 100644 --- a/patches/minecraft/net/minecraft/world/WorldEntitySpawner.java.patch +++ b/patches/minecraft/net/minecraft/world/WorldEntitySpawner.java.patch @@ -50,7 +50,21 @@ { continue label134; } -@@ -228,8 +232,9 @@ +@@ -219,6 +223,13 @@ + } + else + { ++ return p_180267_0_.canSpawnAt(p_180267_1_, p_180267_2_); ++ } ++ } ++ ++ public static boolean canCreatureTypeSpawnBody(EntityLiving.SpawnPlacementType p_180267_0_, World p_180267_1_, BlockPos p_180267_2_) ++ { ++ { + IBlockState iblockstate = p_180267_1_.func_180495_p(p_180267_2_); + + if (p_180267_0_ == EntityLiving.SpawnPlacementType.IN_WATER) +@@ -228,8 +239,9 @@ else { BlockPos blockpos = p_180267_2_.func_177977_b(); @@ -61,7 +75,7 @@ { return false; } -@@ -273,7 +278,7 @@ +@@ -273,7 +285,7 @@ try { @@ -70,7 +84,7 @@ } catch (Exception exception) { -@@ -281,6 +286,7 @@ +@@ -281,6 +293,7 @@ continue; } diff --git a/src/main/java/net/minecraftforge/common/util/EnumHelper.java b/src/main/java/net/minecraftforge/common/util/EnumHelper.java index e3f71c736..7d885c1d9 100644 --- a/src/main/java/net/minecraftforge/common/util/EnumHelper.java +++ b/src/main/java/net/minecraftforge/common/util/EnumHelper.java @@ -21,20 +21,22 @@ package net.minecraftforge.common.util; import java.lang.reflect.*; import java.util.*; +import java.util.function.BiPredicate; import com.google.common.base.Predicate; import com.google.common.collect.Lists; -import net.minecraft.entity.passive.IAnimals; import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.FMLLog; import net.minecraft.block.BlockPressurePlate.Sensitivity; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnumEnchantmentType; +import net.minecraft.entity.EntityLiving; 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.passive.IAnimals; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; @@ -42,9 +44,11 @@ import net.minecraft.item.Item; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; import org.apache.commons.lang3.ArrayUtils; @@ -76,7 +80,8 @@ public class EnumHelper {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, {EnumRarity.class, TextFormatting.class, String.class}, - {HorseArmorType.class, String.class, int.class} + {HorseArmorType.class, String.class, int.class}, + {EntityLiving.SpawnPlacementType.class, BiPredicate.class} }; @Nullable @@ -145,6 +150,12 @@ public class EnumHelper return addEnum(EnumRarity.class, name, color, displayName); } + @Nullable + public static EntityLiving.SpawnPlacementType addSpawnPlacementType(String name, BiPredicate predicate) + { + return addEnum(EntityLiving.SpawnPlacementType.class, name, predicate); + } + /** * * @param name the name of the new {@code HorseArmorType} diff --git a/src/main/resources/forge.exc b/src/main/resources/forge.exc index 3cbcfe114..ff2c10d2e 100644 --- a/src/main/resources/forge.exc +++ b/src/main/resources/forge.exc @@ -27,6 +27,8 @@ net/minecraft/world/World.getBiomeForCoordsBody(Lnet/minecraft/util/math/BlockPo net/minecraft/world/World.markAndNotifyBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/block/state/IBlockState;I)V=|p_180501_1_,chunk,iblockstate,p_180501_2_,p_180501_3_ net/minecraft/world/World.getCloudColorBody(F)Lnet/minecraft/util/math/Vec3d;=|p_72824_1_ net/minecraft/world/WorldServer.canMineBlockBody(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/BlockPos;)Z=|p_175660_1_,p_175660_2_ +net/minecraft/world/WorldEntitySpawner.canCreatureTypeSpawnBody(Lnet/minecraft/entity/EntityLiving$SpawnPlacementType;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z=|p_180267_0_,p_180267_1_,p_180267_2_ + net/minecraft/world/biome/Biome.(IZ)V=|p_i1971_1_,register net/minecraft/world/chunk/storage/AnvilChunkLoader.loadChunk__Async(Lnet/minecraft/world/World;II)[Ljava/lang/Object;=|p_75815_1_,p_75815_2_,p_75815_3_ net/minecraft/world/chunk/storage/AnvilChunkLoader.checkedReadChunkFromNBT__Async(Lnet/minecraft/world/World;IILnet/minecraft/nbt/NBTTagCompound;)[Ljava/lang/Object;=|p_75822_1_,p_75822_2_,p_75822_3_,p_75822_4_ diff --git a/src/test/java/net/minecraftforge/debug/entity/living/CustomSpawnPlacementTest.java b/src/test/java/net/minecraftforge/debug/entity/living/CustomSpawnPlacementTest.java new file mode 100644 index 000000000..ba36a829c --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/entity/living/CustomSpawnPlacementTest.java @@ -0,0 +1,46 @@ +/* + * 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.entity.living; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntitySpawnPlacementRegistry; +import net.minecraft.entity.monster.EntityStray; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; + +@Mod(modid = CustomSpawnPlacementTest.MOD_ID, name = "Custom SpawnPlacementType test mod", version = "1.0", acceptableRemoteVersions = "*") +public class CustomSpawnPlacementTest +{ + static final String MOD_ID = "custom_spawn_placement_test"; + static final boolean ENABLED = false; + static final EntityLiving.SpawnPlacementType CUSTOM = EnumHelper.addSpawnPlacementType("CUSTOM", (world, pos) -> world.getBlockState(pos.down()).getMaterial() == Material.ICE); + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) + { + if (ENABLED) + { + // needs edit to EntitySpawnPlacementRegistry to work + EntitySpawnPlacementRegistry.setPlacementType(EntityStray.class, CUSTOM); + } + } +} diff --git a/src/test/java/net/minecraftforge/test/EnumHelperTest.java b/src/test/java/net/minecraftforge/test/EnumHelperTest.java index 4a2f5e589..db2db44ee 100644 --- a/src/test/java/net/minecraftforge/test/EnumHelperTest.java +++ b/src/test/java/net/minecraftforge/test/EnumHelperTest.java @@ -22,6 +22,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.EntityLiving; import net.minecraft.entity.passive.HorseArmorType; import net.minecraft.init.Bootstrap; import net.minecraftforge.client.EnumHelperClient; @@ -110,6 +111,10 @@ public class EnumHelperTest { filter = true; //We don't want people using this method. } + if (returnType == EntityLiving.SpawnPlacementType.class && declaredConstructor.getParameterTypes().length == 2) + { + 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.