diff --git a/forge/forge_client/src/net/minecraft/src/mod_MinecraftForge.java b/forge/forge_client/src/net/minecraft/src/mod_MinecraftForge.java index e5cee65ce..3d62095d5 100644 --- a/forge/forge_client/src/net/minecraft/src/mod_MinecraftForge.java +++ b/forge/forge_client/src/net/minecraft/src/mod_MinecraftForge.java @@ -10,6 +10,9 @@ import net.minecraft.src.forge.NetworkMod; */ public class mod_MinecraftForge extends NetworkMod { + @MLProp(info = "Set to false to reproduce a vinella bug that prevents mobs from spawning on inverted half-slabs and inverted stairs.") + public static boolean SPAWNER_ALLOW_ON_INVERTED = true; + @Override public String getVersion() { diff --git a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java index c9c71e7df..f34c31e0f 100644 --- a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java +++ b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java @@ -11,6 +11,7 @@ import net.minecraft.src.Chunk; import net.minecraft.src.ChunkCoordIntPair; import net.minecraft.src.Entity; import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityLiving; import net.minecraft.src.EntityMinecart; import net.minecraft.src.EntityPlayer; import net.minecraft.src.IInventory; @@ -339,6 +340,19 @@ public class ForgeHooks return 0; } static LinkedList fuelHandlers = new LinkedList(); + + public static boolean onEntitySpawnSpecial(EntityLiving entity, World world, float x, float y, float z) + { + for (ISpecialMobSpawnHandler handler : specialMobSpawnHandlers) + { + if (handler.onSpecialEntitySpawn(entity, world, x, y, z)) + { + return true; + } + } + return false; + } + static LinkedList specialMobSpawnHandlers = new LinkedList(); // Plant Management // ------------------------------------------------------------ diff --git a/forge/forge_common/net/minecraft/src/forge/ISpecialMobSpawnHandler.java b/forge/forge_common/net/minecraft/src/forge/ISpecialMobSpawnHandler.java new file mode 100644 index 000000000..5e1658592 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/ISpecialMobSpawnHandler.java @@ -0,0 +1,28 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.EntityLiving; +import net.minecraft.src.World; + +public interface ISpecialMobSpawnHandler +{ + /** + * Raised when a Entity is spawned into the world from natural means, meaning + * not by command, MobSpawner, cheat, etc.. Just naturally throughout the world. + * + * This allows the mod to create special functionality that runs on a mob natural + * spawn. The Vanilla minecraft mechanic of having 'Spider Jockies', the color of + * sheep's wool, and Ocelot's spawning with babies can be canceled by returning + * true from this function + * + * Returning true will indicate that you have performed your special spawning, + * and no more handling will be done. + * + * @param entity The newly spawned entity + * @param world The world the entity is in + * @param x The Entitie's X Position + * @param y The Entitie's Y Position + * @param z The Entitie's Z Position + * @return True to prevent any further special case handling from executing. + */ + public boolean onSpecialEntitySpawn(EntityLiving entity, World world, float x, float y, float z); +} diff --git a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java index bf66882e8..b4506999b 100755 --- a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java +++ b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java @@ -152,6 +152,15 @@ public class MinecraftForge ForgeHooks.fuelHandlers.add(handler); } + /** + * Register a new Special Mob Spawn handler + * @param handler The handler to be registered + */ + public static void registerSpecialMobSpawnHandler(ISpecialMobSpawnHandler handler) + { + ForgeHooks.specialMobSpawnHandlers.add(handler); + } + /** * This is not supposed to be called outside of Minecraft internals. */ diff --git a/forge/forge_server/src/net/minecraft/src/mod_MinecraftForge.java b/forge/forge_server/src/net/minecraft/src/mod_MinecraftForge.java index fbec94227..17f538553 100644 --- a/forge/forge_server/src/net/minecraft/src/mod_MinecraftForge.java +++ b/forge/forge_server/src/net/minecraft/src/mod_MinecraftForge.java @@ -11,6 +11,9 @@ import net.minecraft.src.forge.NetworkMod; */ public class mod_MinecraftForge extends NetworkMod { + @MLProp(info = "Set to false to reproduce a vinella bug that prevents mobs from spawning on inverted half-slabs and inverted stairs.") + public static boolean SPAWNER_ALLOW_ON_INVERTED = true; + @Override public String getVersion() { @@ -38,6 +41,5 @@ public class mod_MinecraftForge extends NetworkMod //Add 131 & 132 to C->S list ((Set)ModLoader.getPrivateValue(Packet.class, null, 3)).add(131); ((Set)ModLoader.getPrivateValue(Packet.class, null, 3)).add(132); - } } diff --git a/forge/patches/minecraft/net/minecraft/src/Block.java.patch b/forge/patches/minecraft/net/minecraft/src/Block.java.patch index 6e261a146..9ab2d7f7d 100644 --- a/forge/patches/minecraft/net/minecraft/src/Block.java.patch +++ b/forge/patches/minecraft/net/minecraft/src/Block.java.patch @@ -80,7 +80,7 @@ { ItemStack var8 = this.createStackedBlock(par6); -@@ -1054,6 +1054,396 @@ +@@ -1054,6 +1054,435 @@ */ public void onFallenUpon(World par1World, int par2, int par3, int par4, Entity par5Entity, float par6) {} @@ -473,6 +473,45 @@ + } + return renderAsNormalBlock() && !hasTileEntity(metadata); + } ++ ++ /** ++ * Determines if a specified mob type can spawn on this block, returning false will ++ * prevent any mob from spawning on the block. ++ * ++ * @param type The Mob Category Type ++ * @param world The current world ++ * @param x The X Position ++ * @param y The Y Position ++ * @param z The Z Position ++ * @return True to allow a mob of the specified category to spawn, false to prevent it. ++ */ ++ public boolean canCreatureSpawn(EnumCreatureType type, World world, int x, int y, int z) ++ { ++ int meta = world.getBlockMetadata(x, y, z); ++ if (this instanceof BlockStep) ++ { ++ if (mod_MinecraftForge.SPAWNER_ALLOW_ON_INVERTED) ++ { ++ return (((meta & 8) == 8) || isOpaqueCube()); ++ } ++ else ++ { ++ return isNormalCube(this.blockID); ++ } ++ } ++ else if (this instanceof BlockStairs) ++ { ++ if (mod_MinecraftForge.SPAWNER_ALLOW_ON_INVERTED) ++ { ++ return ((meta & 4) != 0); ++ } ++ else ++ { ++ return isNormalCube(this.blockID); ++ } ++ } ++ return isBlockSolidOnSide(world, x, y, z, 1); ++ } + static { diff --git a/forge/patches/minecraft/net/minecraft/src/SpawnerAnimals.java.patch b/forge/patches/minecraft/net/minecraft/src/SpawnerAnimals.java.patch index c5918f0a0..a4f736019 100644 --- a/forge/patches/minecraft/net/minecraft/src/SpawnerAnimals.java.patch +++ b/forge/patches/minecraft/net/minecraft/src/SpawnerAnimals.java.patch @@ -1,11 +1,42 @@ --- ../src_base/minecraft/net/minecraft/src/SpawnerAnimals.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft/net/minecraft/src/SpawnerAnimals.java 0000-00-00 00:00:00.000000000 -0000 -@@ -202,7 +202,7 @@ +@@ -5,6 +5,8 @@ + import java.util.List; + import java.util.Random; + ++import net.minecraft.src.forge.ForgeHooks; ++ + public final class SpawnerAnimals + { + /** The 17x17 area around the player where mobs can spawn */ +@@ -20,7 +22,7 @@ + { + Chunk var3 = par0World.getChunkFromChunkCoords(par1, par2); + int var4 = par1 * 16 + par0World.rand.nextInt(16); +- int var5 = par0World.rand.nextInt(var3 == null ? 128 : Math.max(128, var3.getTopFilledSegment())); ++ int var5 = par0World.rand.nextInt(var3 == null ? 128 : Math.max(128, var3.getTopFilledSegment() + 15)); //Vanilla Bug that causes mobs to not spawn on the topmost chunk with blocks. + int var6 = par2 * 16 + par0World.rand.nextInt(16); + return new ChunkPosition(var4, var5, var6); + } +@@ -202,7 +204,8 @@ else { int var5 = par1World.getBlockId(par2, par3 - 1, par4); - return Block.isNormalCube(var5) && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); -+ return par1World.isBlockSolidOnSide(par2, par3 - 1, par4, 1) && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); ++ boolean spawnBlock = (Block.blocksList[var5] != null && Block.blocksList[var5].canCreatureSpawn(par0EnumCreatureType, par1World, par2, par3 - 1, par4)); ++ return spawnBlock && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); } } +@@ -211,6 +214,11 @@ + */ + private static void creatureSpecificInit(EntityLiving par0EntityLiving, World par1World, float par2, float par3, float par4) + { ++ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4)) ++ { ++ return; ++ } ++ + if (par0EntityLiving instanceof EntitySpider && par1World.rand.nextInt(100) == 0) + { + EntitySkeleton var7 = new EntitySkeleton(par1World); diff --git a/forge/patches/minecraft_server/net/minecraft/src/Block.java.patch b/forge/patches/minecraft_server/net/minecraft/src/Block.java.patch index fabf44637..c3656209e 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/Block.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/Block.java.patch @@ -68,7 +68,7 @@ { ItemStack var8 = this.createStackedBlock(par6); -@@ -970,6 +972,396 @@ +@@ -970,6 +972,435 @@ */ public void onFallenUpon(World par1World, int par2, int par3, int par4, Entity par5Entity, float par6) {} @@ -461,6 +461,45 @@ + } + return renderAsNormalBlock() && !hasTileEntity(metadata); + } ++ ++ /** ++ * Determines if a specified mob type can spawn on this block, returning false will ++ * prevent any mob from spawning on the block. ++ * ++ * @param type The Mob Category Type ++ * @param world The current world ++ * @param x The X Position ++ * @param y The Y Position ++ * @param z The Z Position ++ * @return True to allow a mob of the specified category to spawn, false to prevent it. ++ */ ++ public boolean canCreatureSpawn(EnumCreatureType type, World world, int x, int y, int z) ++ { ++ int meta = world.getBlockMetadata(x, y, z); ++ if (this instanceof BlockStep) ++ { ++ if (mod_MinecraftForge.SPAWNER_ALLOW_ON_INVERTED) ++ { ++ return (((meta & 8) == 8) || isOpaqueCube()); ++ } ++ else ++ { ++ return isNormalCube(this.blockID); ++ } ++ } ++ else if (this instanceof BlockStairs) ++ { ++ if (mod_MinecraftForge.SPAWNER_ALLOW_ON_INVERTED) ++ { ++ return ((meta & 4) != 0); ++ } ++ else ++ { ++ return isNormalCube(this.blockID); ++ } ++ } ++ return isBlockSolidOnSide(world, x, y, z, 1); ++ } + static { diff --git a/forge/patches/minecraft_server/net/minecraft/src/SpawnerAnimals.java.patch b/forge/patches/minecraft_server/net/minecraft/src/SpawnerAnimals.java.patch index ef9316939..55bb1bb00 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/SpawnerAnimals.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/SpawnerAnimals.java.patch @@ -1,11 +1,42 @@ --- ../src_base/minecraft_server/net/minecraft/src/SpawnerAnimals.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft_server/net/minecraft/src/SpawnerAnimals.java 0000-00-00 00:00:00.000000000 -0000 -@@ -202,7 +202,7 @@ +@@ -5,6 +5,8 @@ + import java.util.List; + import java.util.Random; + ++import net.minecraft.src.forge.ForgeHooks; ++ + public final class SpawnerAnimals + { + /** The 17x17 area around the player where mobs can spawn */ +@@ -20,7 +22,7 @@ + { + Chunk var3 = par0World.getChunkFromChunkCoords(par1, par2); + int var4 = par1 * 16 + par0World.rand.nextInt(16); +- int var5 = par0World.rand.nextInt(var3 == null ? 128 : Math.max(128, var3.getTopFilledSegment())); ++ int var5 = par0World.rand.nextInt(var3 == null ? 128 : Math.max(128, var3.getTopFilledSegment() + 15)); //Vanilla Bug that causes mobs to not spawn on the topmost chunk with blocks. + int var6 = par2 * 16 + par0World.rand.nextInt(16); + return new ChunkPosition(var4, var5, var6); + } +@@ -202,7 +204,8 @@ else { int var5 = par1World.getBlockId(par2, par3 - 1, par4); - return Block.isNormalCube(var5) && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); -+ return par1World.isBlockSolidOnSide(par2, par3 - 1, par4, 1) && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); ++ boolean spawnBlock = (Block.blocksList[var5] != null && Block.blocksList[var5].canCreatureSpawn(par0EnumCreatureType, par1World, par2, par3 - 1, par4)); ++ return spawnBlock && var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4) && !par1World.getBlockMaterial(par2, par3, par4).isLiquid() && !par1World.isBlockNormalCube(par2, par3 + 1, par4); } } +@@ -211,6 +214,11 @@ + */ + private static void creatureSpecificInit(EntityLiving par0EntityLiving, World par1World, float par2, float par3, float par4) + { ++ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4)) ++ { ++ return; ++ } ++ + if (par0EntityLiving instanceof EntitySpider && par1World.rand.nextInt(100) == 0) + { + EntitySkeleton var7 = new EntitySkeleton(par1World);