diff --git a/IronChests2/common/cpw/mods/ironchest/IronChestAIOcelotSit.java b/IronChests2/common/cpw/mods/ironchest/IronChestAIOcelotSit.java new file mode 100644 index 0000000..167f894 --- /dev/null +++ b/IronChests2/common/cpw/mods/ironchest/IronChestAIOcelotSit.java @@ -0,0 +1,138 @@ +package cpw.mods.ironchest; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import net.minecraft.src.Block; +import net.minecraft.src.BlockBed; +import net.minecraft.src.EntityAIBase; +import net.minecraft.src.EntityAIOcelotSit; +import net.minecraft.src.EntityOcelot; +import net.minecraft.src.TileEntityChest; +import net.minecraft.src.World; + +public class IronChestAIOcelotSit extends EntityAIBase { + private EntityOcelot ocelot; + private final float speed; + private int ticksRun = 0; + private int tryTicks = 0; + private int maxTicks = 0; + private int targetX = 0; + private int targetY = 0; + private int targetZ = 0; + private EntityAIOcelotSit sitAI; + private Method isTargetBlockMethod; + private boolean grabbedMethod; + + public IronChestAIOcelotSit(EntityOcelot par1EntityOcelot, float par2, EntityAIOcelotSit sitAI) { + this.ocelot = par1EntityOcelot; + this.speed = par2; + this.sitAI = sitAI; + this.setMutexBits(5); + if (!grabbedMethod) { + try { + isTargetBlockMethod = EntityAIOcelotSit.class.getDeclaredMethod("a", World.class, int.class, int.class, int.class); + } catch (Exception e) { + // Can't find it + try { + isTargetBlockMethod = EntityAIOcelotSit.class.getDeclaredMethod("func_50078_a", World.class, int.class, int.class, int.class); + } catch (Exception e1) { + } + } + isTargetBlockMethod.setAccessible(true); + grabbedMethod = true; + } + } + + public boolean shouldExecute() + { + return ocelot.isTamed() && !ocelot.isSitting() && ocelot.getRNG().nextDouble() <= 0.0065D && thereIsChestNearby(); + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean continueExecuting() + { + return this.ticksRun <= this.maxTicks && this.tryTicks <= 60 && isBlockAChestBlock(ocelot.worldObj, this.targetX, this.targetY, this.targetZ); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.ocelot.getNavigator().tryMoveToXYZ((double) ((float) this.targetX) + 0.5D, (double) (this.targetY + 1), (double) ((float) this.targetZ) + 0.5D, + this.speed); + this.ticksRun = 0; + this.tryTicks = 0; + this.maxTicks = this.ocelot.getRNG().nextInt(this.ocelot.getRNG().nextInt(1200) + 1200) + 1200; + this.ocelot.func_50008_ai().setIsSitting(false); + } + + /** + * Resets the task + */ + public void resetTask() + { + this.ocelot.setSitting(false); + } + + /** + * Updates the task + */ + public void updateTask() + { + ++this.ticksRun; + this.ocelot.func_50008_ai().setIsSitting(false); + + if (this.ocelot.getDistanceSq((double) this.targetX, (double) (this.targetY + 1), (double) this.targetZ) > 1.0D) + { + this.ocelot.setSitting(false); + this.ocelot.getNavigator().tryMoveToXYZ((double) ((float) this.targetX) + 0.5D, (double) (this.targetY + 1), (double) ((float) this.targetZ) + 0.5D, + this.speed); + ++this.tryTicks; + } + else if (!this.ocelot.isSitting()) + { + this.ocelot.setSitting(true); + } + else + { + --this.tryTicks; + } + } + + private boolean thereIsChestNearby() { + int searchY = (int) this.ocelot.posY; + double closestChestDistance = Integer.MAX_VALUE; + + for (int searchX = (int) this.ocelot.posX - 8; searchX < this.ocelot.posX + 8; searchX++) { + for (int searchZ = (int) this.ocelot.posZ - 8; searchZ < this.ocelot.posZ + 8; searchZ++) { + if (this.isBlockAChestBlock(this.ocelot.worldObj, searchX, searchY, searchZ) && this.ocelot.worldObj.isAirBlock(searchX, searchY + 1, searchZ)) { + double chestDistance = this.ocelot.getDistanceSq((double) searchX, (double) searchY, (double) searchZ); + + if (chestDistance < closestChestDistance) { + this.targetX = searchX; + this.targetY = searchY; + this.targetZ = searchZ; + closestChestDistance = chestDistance; + } + } + } + } + + return closestChestDistance < Integer.MAX_VALUE; + } + + private boolean isBlockAChestBlock(World world, int x, int y, int z) { + if (world.getBlockId(x, y, z)==mod_IronChest.ironChestBlock.blockID) { + return true; + } + try { + return (Boolean) isTargetBlockMethod.invoke(sitAI, world, x, y, z); + } catch (Exception e) { + } + return false; + } +} diff --git a/IronChests2/common/cpw/mods/ironchest/OcelotsSitOnChestsHandler.java b/IronChests2/common/cpw/mods/ironchest/OcelotsSitOnChestsHandler.java new file mode 100644 index 0000000..99cfd07 --- /dev/null +++ b/IronChests2/common/cpw/mods/ironchest/OcelotsSitOnChestsHandler.java @@ -0,0 +1,28 @@ +package cpw.mods.ironchest; + +import java.util.List; + +import cpw.mods.fml.common.ReflectionHelper; +import net.minecraft.src.EntityAIBase; +import net.minecraft.src.EntityAIOcelotSit; +import net.minecraft.src.EntityAITasks; +import net.minecraft.src.EntityLiving; +import net.minecraft.src.EntityOcelot; +import net.minecraft.src.World; +import net.minecraft.src.forge.IEntityLivingHandler; +import net.minecraft.src.forge.adaptors.EntityLivingHandlerAdaptor; + +public class OcelotsSitOnChestsHandler extends EntityLivingHandlerAdaptor { + private static EntityAIOcelotSit aiTask = new EntityAIOcelotSit(null, 0); + @Override + public boolean onEntityLivingUpdate(EntityLiving entity) { + if (entity.ticksExisted<2 && entity instanceof EntityOcelot) { + EntityOcelot ocelot = (EntityOcelot) entity; + EntityAITasks ocelotTasks = ReflectionHelper.getPrivateValue(EntityLiving.class, ocelot, "tasks"); + List taskList = ReflectionHelper.getPrivateValue(EntityAITasks.class, ocelotTasks, "tasksToDo"); + taskList.remove(5); + ocelotTasks.addTask(6, new IronChestAIOcelotSit(ocelot, 0.4F, aiTask)); + } + return false; + } +} diff --git a/IronChests2/common/cpw/mods/ironchest/mod_IronChest.java b/IronChests2/common/cpw/mods/ironchest/mod_IronChest.java index f46ed78..fefe4f7 100644 --- a/IronChests2/common/cpw/mods/ironchest/mod_IronChest.java +++ b/IronChests2/common/cpw/mods/ironchest/mod_IronChest.java @@ -21,6 +21,7 @@ import net.minecraft.src.SidedProxy; import net.minecraft.src.forge.Configuration; import net.minecraft.src.forge.MinecraftForge; import net.minecraft.src.forge.NetworkMod; +import net.minecraft.src.forge.adaptors.EntityLivingHandlerAdaptor; public class mod_IronChest extends NetworkMod { @@ -29,6 +30,7 @@ public class mod_IronChest extends NetworkMod { public static IProxy proxy; public static mod_IronChest instance; public static boolean CACHE_RENDER = true; + public static boolean OCELOTS_SITONCHESTS = true; @Override public String getVersion() { @@ -51,6 +53,7 @@ public class mod_IronChest extends NetworkMod { ironChestBlock = new BlockIronChest(bId); ChestChangerType.buildItems(cfg, 29501); CACHE_RENDER = cfg.getOrCreateBooleanProperty("cacheRenderingInformation", Configuration.CATEGORY_GENERAL, true).getBoolean(true); + OCELOTS_SITONCHESTS = cfg.getOrCreateBooleanProperty("ocelotsSitOnChests", Configuration.CATEGORY_GENERAL, true).getBoolean(true); } catch (Exception e) { ModLoader.getLogger().severe("IronChest was unable to load it's configuration successfully"); e.printStackTrace(System.err); @@ -68,6 +71,7 @@ public class mod_IronChest extends NetworkMod { MinecraftForge.setGuiHandler(this, proxy); MinecraftForge.registerConnectionHandler(new PacketHandler()); proxy.registerRenderInformation(); + MinecraftForge.registerEntityLivingHandler(new OcelotsSitOnChestsHandler()); } @Override