Fixed Vinella mob spawning bug that prevented mobs from spawning on the top most chunk. Added new Block function to determine if a Mob can naturally spawn on the block. Add new hook to allow for special case handeling on natural entity spawn.

This commit is contained in:
LexManos 2012-04-25 01:37:06 -07:00
parent 33a3f67225
commit cbc9d73a9a
9 changed files with 203 additions and 7 deletions

View File

@ -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()
{

View File

@ -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<IFuelHandler> fuelHandlers = new LinkedList<IFuelHandler>();
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<ISpecialMobSpawnHandler> specialMobSpawnHandlers = new LinkedList<ISpecialMobSpawnHandler>();
// Plant Management
// ------------------------------------------------------------

View File

@ -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);
}

View File

@ -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.
*/

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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);

View File

@ -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
{

View File

@ -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);