From 7d690ad598abf935b36cf51e83458f293e955f0e Mon Sep 17 00:00:00 2001 From: WayofTime Date: Mon, 29 Aug 2016 18:56:21 -0400 Subject: [PATCH] Generalized the demon entity AI logic. Also improved the behaviour of the mimic entities. --- changelog.txt | 4 + .../entity/ai/EntityAIAttackRangedBow.java | 8 +- .../entity/ai/EntityAIFollowOwner.java | 6 +- .../entity/ai/EntityAIMimicReform.java | 32 ++ .../entity/ai/EntityAIOwnerHurtByTarget.java | 6 +- .../entity/ai/EntityAIOwnerHurtTarget.java | 18 +- .../entity/ai/EntityAIRetreatToHeal.java | 12 +- .../entity/mob/EntityDemonBase.java | 361 ++++++++++++++++++ .../bloodmagic/entity/mob/EntityMimic.java | 54 ++- .../entity/mob/EntitySentientSpecter.java | 224 +---------- .../WayofTime/bloodmagic/tile/TileMimic.java | 2 +- 11 files changed, 457 insertions(+), 270 deletions(-) create mode 100644 src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIMimicReform.java create mode 100644 src/main/java/WayofTime/bloodmagic/entity/mob/EntityDemonBase.java diff --git a/changelog.txt b/changelog.txt index c3c4b222..a9d3bfc1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,10 @@ Version 2.0.4-57 ------------------------------------------------------ - Changed the Demon Will Aura Gauge so it refreshes based on the player's ticks existed +- Made Draft of Angelus craftable with gold dust +- Fixed Elytra upgrade +- Added the Mimics - the real ones +- Implemented a bit of framework for some T5 shenanigans. ------------------------------------------------------ Version 2.0.4-56 diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIAttackRangedBow.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIAttackRangedBow.java index de8423df..09db9725 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIAttackRangedBow.java +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIAttackRangedBow.java @@ -4,11 +4,11 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.item.ItemBow; import net.minecraft.util.EnumHand; -import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; +import WayofTime.bloodmagic.entity.mob.EntityDemonBase; public class EntityAIAttackRangedBow extends EntityAIBase { - private final EntitySentientSpecter entity; + private final EntityDemonBase entity; private final double moveSpeedAmp; private int attackCooldown; private final float maxAttackDistance; @@ -18,9 +18,9 @@ public class EntityAIAttackRangedBow extends EntityAIBase private boolean strafingBackwards; private int strafingTime = -1; - public EntityAIAttackRangedBow(EntitySentientSpecter specter, double speedAmplifier, int delay, float maxDistance) + public EntityAIAttackRangedBow(EntityDemonBase entityDemonBase, double speedAmplifier, int delay, float maxDistance) { - this.entity = specter; + this.entity = entityDemonBase; this.moveSpeedAmp = speedAmplifier; this.attackCooldown = delay; this.maxAttackDistance = maxDistance * maxDistance; diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIFollowOwner.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIFollowOwner.java index db3d437c..7227f8cf 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIFollowOwner.java +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIFollowOwner.java @@ -12,11 +12,11 @@ import net.minecraft.pathfinding.PathNodeType; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; -import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; +import WayofTime.bloodmagic.entity.mob.EntityDemonBase; public class EntityAIFollowOwner extends EntityAIBase { - private EntitySentientSpecter thePet; + private EntityDemonBase thePet; private EntityLivingBase theOwner; World theWorld; private double followSpeed; @@ -26,7 +26,7 @@ public class EntityAIFollowOwner extends EntityAIBase float minDist; private float oldWaterCost; - public EntityAIFollowOwner(EntitySentientSpecter thePetIn, double followSpeedIn, float minDistIn, float maxDistIn) + public EntityAIFollowOwner(EntityDemonBase thePetIn, double followSpeedIn, float minDistIn, float maxDistIn) { this.thePet = thePetIn; this.theWorld = thePetIn.worldObj; diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIMimicReform.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIMimicReform.java new file mode 100644 index 00000000..b7e63c30 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIMimicReform.java @@ -0,0 +1,32 @@ +package WayofTime.bloodmagic.entity.ai; + +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.math.BlockPos; +import WayofTime.bloodmagic.entity.mob.EntityMimic; + +public class EntityAIMimicReform extends EntityAIBase +{ + private final EntityMimic theEntity; + + public EntityAIMimicReform(EntityMimic creatureIn) + { + this.theEntity = creatureIn; + this.setMutexBits(2); + } + + @Override + public boolean shouldExecute() + { + return this.theEntity.ticksExisted > 100 && this.theEntity.hasHome() && this.theEntity.isWithinHomeDistanceCurrentPosition(); + } + + @Override + public void startExecuting() + { + BlockPos homePos = this.theEntity.getHomePosition(); + if (theEntity.reformIntoMimicBlock(homePos)) + { + this.theEntity.setDead(); + } + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtByTarget.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtByTarget.java index 004db27d..ef8ca421 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtByTarget.java +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtByTarget.java @@ -2,15 +2,15 @@ package WayofTime.bloodmagic.entity.ai; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAITarget; -import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; +import WayofTime.bloodmagic.entity.mob.EntityDemonBase; public class EntityAIOwnerHurtByTarget extends EntityAITarget { - EntitySentientSpecter theDefendingTameable; + EntityDemonBase theDefendingTameable; EntityLivingBase theOwnerAttacker; private int timestamp; - public EntityAIOwnerHurtByTarget(EntitySentientSpecter theDefendingTameableIn) + public EntityAIOwnerHurtByTarget(EntityDemonBase theDefendingTameableIn) { super(theDefendingTameableIn, false); this.theDefendingTameable = theDefendingTameableIn; diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtTarget.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtTarget.java index cf65a828..5c7ee8f2 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtTarget.java +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIOwnerHurtTarget.java @@ -2,18 +2,18 @@ package WayofTime.bloodmagic.entity.ai; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAITarget; -import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; +import WayofTime.bloodmagic.entity.mob.EntityDemonBase; public class EntityAIOwnerHurtTarget extends EntityAITarget { - EntitySentientSpecter theEntitySentientSpecter; + EntityDemonBase theEntityDemonBase; EntityLivingBase theTarget; private int timestamp; - public EntityAIOwnerHurtTarget(EntitySentientSpecter theEntitySentientSpecterIn) + public EntityAIOwnerHurtTarget(EntityDemonBase theEntityDemonBaseIn) { - super(theEntitySentientSpecterIn, false); - this.theEntitySentientSpecter = theEntitySentientSpecterIn; + super(theEntityDemonBaseIn, false); + this.theEntityDemonBase = theEntityDemonBaseIn; this.setMutexBits(1); } @@ -22,12 +22,12 @@ public class EntityAIOwnerHurtTarget extends EntityAITarget */ public boolean shouldExecute() { - if (!this.theEntitySentientSpecter.isTamed()) + if (!this.theEntityDemonBase.isTamed()) { return false; } else { - EntityLivingBase entitylivingbase = this.theEntitySentientSpecter.getOwner(); + EntityLivingBase entitylivingbase = this.theEntityDemonBase.getOwner(); if (entitylivingbase == null) { @@ -36,7 +36,7 @@ public class EntityAIOwnerHurtTarget extends EntityAITarget { this.theTarget = entitylivingbase.getLastAttacker(); int i = entitylivingbase.getLastAttackerTime(); - return i != this.timestamp && this.isSuitableTarget(this.theTarget, false) && this.theEntitySentientSpecter.shouldAttackEntity(this.theTarget, entitylivingbase); + return i != this.timestamp && this.isSuitableTarget(this.theTarget, false) && this.theEntityDemonBase.shouldAttackEntity(this.theTarget, entitylivingbase); } } } @@ -47,7 +47,7 @@ public class EntityAIOwnerHurtTarget extends EntityAITarget public void startExecuting() { this.taskOwner.setAttackTarget(this.theTarget); - EntityLivingBase entitylivingbase = this.theEntitySentientSpecter.getOwner(); + EntityLivingBase entitylivingbase = this.theEntityDemonBase.getOwner(); if (entitylivingbase != null) { diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIRetreatToHeal.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIRetreatToHeal.java index d6528e28..c4b08304 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIRetreatToHeal.java +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIRetreatToHeal.java @@ -11,7 +11,7 @@ import net.minecraft.pathfinding.Path; import net.minecraft.pathfinding.PathNavigate; import net.minecraft.util.EntitySelectors; import net.minecraft.util.math.Vec3d; -import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; +import WayofTime.bloodmagic.entity.mob.EntityDemonBase; import com.google.common.base.Predicate; import com.google.common.base.Predicates; @@ -20,7 +20,7 @@ public class EntityAIRetreatToHeal extends EntityAIBase { private final Predicate canBeSeenSelector; /** The entity we are attached to */ - protected EntitySentientSpecter theEntity; + protected EntityDemonBase theEntity; private double farSpeed; private double nearSpeed; private double safeHealDistance = 3; @@ -33,12 +33,12 @@ public class EntityAIRetreatToHeal extends EntityAIBase private Class classToAvoid; private Predicate avoidTargetSelector; - public EntityAIRetreatToHeal(EntitySentientSpecter theEntityIn, Class classToAvoidIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn) + public EntityAIRetreatToHeal(EntityDemonBase theEntityIn, Class classToAvoidIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn) { this(theEntityIn, classToAvoidIn, Predicates.alwaysTrue(), avoidDistanceIn, farSpeedIn, nearSpeedIn); } - public EntityAIRetreatToHeal(EntitySentientSpecter theEntityIn, Class classToAvoidIn, Predicate avoidTargetSelectorIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn) + public EntityAIRetreatToHeal(EntityDemonBase theEntityIn, Class classToAvoidIn, Predicate avoidTargetSelectorIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn) { this.canBeSeenSelector = new Predicate() { @@ -63,7 +63,7 @@ public class EntityAIRetreatToHeal extends EntityAIBase @Override public boolean shouldExecute() { - if (!this.theEntity.shouldSelfHeal()) + if (!this.theEntity.shouldEmergencyHeal()) { return false; } @@ -99,7 +99,7 @@ public class EntityAIRetreatToHeal extends EntityAIBase @Override public boolean continueExecuting() { - return this.theEntity.shouldSelfHeal();//!this.entityPathNavigate.noPath(); + return this.theEntity.shouldEmergencyHeal();//!this.entityPathNavigate.noPath(); } /** diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityDemonBase.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityDemonBase.java new file mode 100644 index 00000000..3f256328 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityDemonBase.java @@ -0,0 +1,361 @@ +package WayofTime.bloodmagic.entity.mob; + +import java.util.UUID; + +import net.minecraft.block.Block; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityCreature; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IEntityOwnable; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.monster.EntityCreeper; +import net.minecraft.entity.monster.EntityGhast; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.passive.EntityHorse; +import net.minecraft.entity.passive.EntityTameable; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.potion.PotionEffect; +import net.minecraft.server.management.PreYggdrasilConverter; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; + +public class EntityDemonBase extends EntityCreature implements IEntityOwnable +{ + protected static final DataParameter TAMED = EntityDataManager.createKey(EntityTameable.class, DataSerializers.BYTE); + protected static final DataParameter> OWNER_UNIQUE_ID = EntityDataManager.>createKey(EntityTameable.class, DataSerializers.OPTIONAL_UNIQUE_ID); + + public EntityDemonBase(World worldIn) + { + super(worldIn); + } + + @Override + protected void entityInit() + { + super.entityInit(); + this.dataManager.register(TAMED, Byte.valueOf((byte) 0)); + this.dataManager.register(OWNER_UNIQUE_ID, Optional.absent()); + } + + @Override + protected void applyEntityAttributes() + { + super.applyEntityAttributes(); + this.getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); + } + + public void setCombatTask() + { + + } + + @Override + public boolean isPotionApplicable(PotionEffect effect) + { + return super.isPotionApplicable(effect); + } + + @Override + public void onLivingUpdate() + { + this.updateArmSwingProgress(); + + super.onLivingUpdate(); + } + + @Override + public boolean attackEntityFrom(DamageSource source, float amount) + { + return this.isEntityInvulnerable(source) ? false : super.attackEntityFrom(source, amount); + } + + /** + * Redone from EntityMob to prevent despawning on peaceful. + */ + @Override + public boolean attackEntityAsMob(Entity attackedEntity) + { + float f = (float) this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); + int i = 0; + + if (attackedEntity instanceof EntityLivingBase) + { + f += EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((EntityLivingBase) attackedEntity).getCreatureAttribute()); + i += EnchantmentHelper.getKnockbackModifier(this); + } + + boolean flag = attackedEntity.attackEntityFrom(DamageSource.causeMobDamage(this), f); + + if (flag) + { + if (i > 0 && attackedEntity instanceof EntityLivingBase) + { + ((EntityLivingBase) attackedEntity).knockBack(this, (float) i * 0.5F, (double) MathHelper.sin(this.rotationYaw * 0.017453292F), (double) (-MathHelper.cos(this.rotationYaw * 0.017453292F))); + this.motionX *= 0.6D; + this.motionZ *= 0.6D; + } + + int j = EnchantmentHelper.getFireAspectModifier(this); + + if (j > 0) + { + attackedEntity.setFire(j * 4); + } + + if (attackedEntity instanceof EntityPlayer) + { + EntityPlayer entityplayer = (EntityPlayer) attackedEntity; + ItemStack itemstack = this.getHeldItemMainhand(); + ItemStack itemstack1 = entityplayer.isHandActive() ? entityplayer.getActiveItemStack() : null; + + if (itemstack != null && itemstack1 != null && itemstack.getItem() instanceof ItemAxe && itemstack1.getItem() == Items.SHIELD) + { + float f1 = 0.25F + (float) EnchantmentHelper.getEfficiencyModifier(this) * 0.05F; + + if (this.rand.nextFloat() < f1) + { + entityplayer.getCooldownTracker().setCooldown(Items.SHIELD, 100); + this.worldObj.setEntityState(entityplayer, (byte) 30); + } + } + } + + this.applyEnchantments(this, attackedEntity); + } + + return flag; + } + + @Override + public void setItemStackToSlot(EntityEquipmentSlot slotIn, ItemStack stack) + { + super.setItemStackToSlot(slotIn, stack); + + if (!this.worldObj.isRemote && slotIn == EntityEquipmentSlot.MAINHAND) + { + this.setCombatTask(); + } + } + + public boolean isStationary() + { + return false; + } + + public boolean absorbExplosion(Explosion explosion) + { + return false; + } + + public void performEmergencyHeal(double toHeal) + { + this.heal((float) toHeal); + + if (worldObj instanceof WorldServer) + { + WorldServer server = (WorldServer) worldObj; + server.spawnParticle(EnumParticleTypes.HEART, this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height), this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, 7, 0.2, 0.2, 0.2, 0, new int[0]); + } + } + + public boolean shouldEmergencyHeal() + { + return this.getHealth() < this.getMaxHealth() * 0.5; + } + + @Override + protected boolean canDespawn() + { + return !this.isTamed() && super.canDespawn(); + } + + @Override + public void writeEntityToNBT(NBTTagCompound tag) + { + super.writeEntityToNBT(tag); + + if (this.getOwnerId() == null) + { + tag.setString("OwnerUUID", ""); + } else + { + tag.setString("OwnerUUID", this.getOwnerId().toString()); + } + + } + + @Override + public void readEntityFromNBT(NBTTagCompound tag) + { + super.readEntityFromNBT(tag); + + String s = ""; + + if (tag.hasKey("OwnerUUID", 8)) + { + s = tag.getString("OwnerUUID"); + } else + { + String s1 = tag.getString("Owner"); + s = PreYggdrasilConverter.convertMobOwnerIfNeeded(this.getServer(), s1); + } + + if (!s.isEmpty()) + { + try + { + this.setOwnerId(UUID.fromString(s)); + this.setTamed(true); + } catch (Throwable var4) + { + this.setTamed(false); + } + } + + this.setCombatTask(); + } + + //TODO: Change to fit the given AI + public boolean shouldAttackEntity(EntityLivingBase attacker, EntityLivingBase owner) + { + if (!(attacker instanceof EntityCreeper) && !(attacker instanceof EntityGhast)) + { + if (attacker instanceof IEntityOwnable) + { + IEntityOwnable entityOwnable = (IEntityOwnable) attacker; + + if (entityOwnable.getOwner() == owner) + { + return false; + } + } + + return attacker instanceof EntityPlayer && owner instanceof EntityPlayer && !((EntityPlayer) owner).canAttackPlayer((EntityPlayer) attacker) ? false : !(attacker instanceof EntityHorse) || !((EntityHorse) attacker).isTame(); + } else + { + return false; + } + } + + public void attackEntityWithRangedAttack(EntityLivingBase target, float velocity) + { + + } + + public boolean isTamed() + { + return (((Byte) this.dataManager.get(TAMED)).byteValue() & 4) != 0; + } + + public void setTamed(boolean tamed) + { + byte b0 = ((Byte) this.dataManager.get(TAMED)).byteValue(); + + if (tamed) + { + this.dataManager.set(TAMED, Byte.valueOf((byte) (b0 | 4))); + } else + { + this.dataManager.set(TAMED, Byte.valueOf((byte) (b0 & -5))); + } + +// this.setupTamedAI(); + } + + @Override + protected SoundEvent getAmbientSound() + { + return SoundEvents.ENTITY_COW_AMBIENT; + } + + @Override + protected SoundEvent getHurtSound() + { + return SoundEvents.ENTITY_COW_HURT; + } + + @Override + protected SoundEvent getDeathSound() + { + return SoundEvents.ENTITY_COW_DEATH; + } + + @Override + protected void playStepSound(BlockPos pos, Block block) + { + this.playSound(SoundEvents.ENTITY_COW_STEP, 0.15F, 1.0F); + } + + /** + * Returns the volume for the sounds this mob makes. + */ + @Override + protected float getSoundVolume() + { + return 0.4F; + } + + @Override + public UUID getOwnerId() + { + return (UUID) (this.dataManager.get(OWNER_UNIQUE_ID)).orNull(); + } + + public void setOwnerId(UUID uuid) + { + this.dataManager.set(OWNER_UNIQUE_ID, Optional.fromNullable(uuid)); + } + + @Override + public EntityLivingBase getOwner() + { + try + { + UUID uuid = this.getOwnerId(); + return uuid == null ? null : this.worldObj.getPlayerEntityByUUID(uuid); + } catch (IllegalArgumentException var2) + { + return null; + } + } + + public void setOwner(EntityPlayer player) + { + setOwnerId(player.getUniqueID()); + } + + public class TargetPredicate implements Predicate + { + EntityDemonBase entity; + + public TargetPredicate(EntityDemonBase entity) + { + this.entity = entity; + } + + @Override + public boolean apply(EntityMob input) + { + return entity.shouldAttackEntity(input, this.entity.getOwner()); + } + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityMimic.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityMimic.java index e54e2f60..18bf3bcb 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityMimic.java +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityMimic.java @@ -9,12 +9,12 @@ import net.minecraft.entity.ai.EntityAIAttackMelee; import net.minecraft.entity.ai.EntityAIHurtByTarget; import net.minecraft.entity.ai.EntityAILeapAtTarget; import net.minecraft.entity.ai.EntityAILookIdle; +import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAISwimming; import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.monster.EntityIronGolem; -import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; @@ -34,10 +34,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import WayofTime.bloodmagic.block.BlockMimic; +import WayofTime.bloodmagic.entity.ai.EntityAIMimicReform; import WayofTime.bloodmagic.registry.ModBlocks; import WayofTime.bloodmagic.tile.TileMimic; -public class EntityMimic extends EntityMob +public class EntityMimic extends EntityDemonBase { /** * Copy of EntitySpider's AI (should be pretty evident...) @@ -53,16 +54,16 @@ public class EntityMimic extends EntityMob { super(worldIn); this.setSize(0.9F, 0.9F); - } - protected void initEntityAI() - { this.tasks.addTask(1, new EntityAISwimming(this)); this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F)); this.tasks.addTask(4, new EntityMimic.AISpiderAttack(this)); - this.tasks.addTask(5, new EntityAIWander(this, 0.8D)); - this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); - this.tasks.addTask(6, new EntityAILookIdle(this)); + this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1)); + this.tasks.addTask(6, new EntityAIWander(this, 0.8D)); + this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + this.tasks.addTask(8, new EntityAILookIdle(this)); + this.tasks.addTask(7, new EntityAIMimicReform(this)); + this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0])); this.targetTasks.addTask(2, new EntityMimic.AISpiderTarget(this, EntityPlayer.class)); this.targetTasks.addTask(3, new EntityMimic.AISpiderTarget(this, EntityIronGolem.class)); @@ -95,7 +96,7 @@ public class EntityMimic extends EntityMob return this.getItemStackFromSlot(EntityEquipmentSlot.CHEST); } - public void setItemStack(ItemStack stack) + public void setMimicItemStack(ItemStack stack) { this.setItemStackToSlot(EntityEquipmentSlot.CHEST, stack); } @@ -128,19 +129,18 @@ public class EntityMimic extends EntityMob return false; } - public void initializeMimic(ItemStack heldStack, NBTTagCompound tileTag, boolean dropItemsOnBreak, int metaOfReplacedBlock, int playerCheckRadius) + public void initializeMimic(ItemStack heldStack, NBTTagCompound tileTag, boolean dropItemsOnBreak, int metaOfReplacedBlock, int playerCheckRadius, BlockPos homePosition) { - this.setItemStack(heldStack); + this.setMimicItemStack(heldStack); this.tileTag = tileTag; this.dropItemsOnBreak = dropItemsOnBreak; this.metaOfReplacedBlock = metaOfReplacedBlock; this.playerCheckRadius = playerCheckRadius; + this.setHomePosAndDistance(homePosition, 2); //TODO: Save this. } - public void reformIntoMimicBlock() + public boolean reformIntoMimicBlock(BlockPos centerPos) { - BlockPos centerPos = this.getPosition(); - int horizontalRadius = 1; int verticalRadius = 1; @@ -162,13 +162,15 @@ public class EntityMimic extends EntityMob BlockPos newPos = centerPos.add(i, j, k); if (spawnMimicBlockAtPosition(worldObj, newPos)) { - return; + return true; } } } } } } + + return false; } @Override @@ -246,8 +248,10 @@ public class EntityMimic extends EntityMob { if (!this.worldObj.isRemote && this.worldObj.getDifficulty() == EnumDifficulty.PEACEFUL) { - reformIntoMimicBlock(); - this.setDead(); + if (reformIntoMimicBlock(this.getPosition())) + { + this.setDead(); + } } super.onUpdate(); @@ -366,20 +370,13 @@ public class EntityMimic extends EntityMob /** * Returns whether an in-progress EntityAIBase should continue executing */ + @Override public boolean continueExecuting() { - float f = this.attacker.getBrightness(1.0F); - - if (f >= 0.5F && this.attacker.getRNG().nextInt(100) == 0) - { - this.attacker.setAttackTarget((EntityLivingBase) null); - return false; - } else - { - return super.continueExecuting(); - } + return super.continueExecuting(); } + @Override protected double getAttackReachSqr(EntityLivingBase attackTarget) { return (double) (4.0F + attackTarget.width); @@ -398,8 +395,7 @@ public class EntityMimic extends EntityMob */ public boolean shouldExecute() { - float f = this.taskOwner.getBrightness(1.0F); - return f >= 0.5F ? false : super.shouldExecute(); + return super.shouldExecute(); } } } \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntitySentientSpecter.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntitySentientSpecter.java index f1b39dd7..d9d7b10a 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/mob/EntitySentientSpecter.java +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntitySentientSpecter.java @@ -2,7 +2,6 @@ package WayofTime.bloodmagic.entity.mob; import java.util.ArrayList; import java.util.List; -import java.util.UUID; import javax.annotation.Nullable; @@ -13,7 +12,6 @@ import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityCreature; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.IEntityOwnable; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAIAttackMelee; import net.minecraft.entity.ai.EntityAILookIdle; @@ -23,26 +21,17 @@ import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntityGhast; -import net.minecraft.entity.monster.EntityMob; -import net.minecraft.entity.passive.EntityHorse; -import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityTippedArrow; import net.minecraft.init.Enchantments; -import net.minecraft.init.Items; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.ItemAxe; import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.datasync.DataParameter; -import net.minecraft.network.datasync.DataSerializers; -import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; -import net.minecraft.server.management.PreYggdrasilConverter; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; @@ -66,14 +55,8 @@ import WayofTime.bloodmagic.entity.ai.EntityAIRetreatToHeal; import WayofTime.bloodmagic.item.soul.ItemSentientBow; import WayofTime.bloodmagic.registry.ModItems; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; - -public class EntitySentientSpecter extends EntityCreature implements IEntityOwnable +public class EntitySentientSpecter extends EntityDemonBase { - protected static final DataParameter TAMED = EntityDataManager.createKey(EntityTameable.class, DataSerializers.BYTE); - protected static final DataParameter> OWNER_UNIQUE_ID = EntityDataManager.>createKey(EntityTameable.class, DataSerializers.OPTIONAL_UNIQUE_ID); - @Getter @Setter protected EnumDemonWillType type = EnumDemonWillType.DESTRUCTIVE; @@ -111,24 +94,16 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna // this.targetTasks.addTask(8, new EntityAINearestAttackableTarget(this, EntityMob.class, 10, true, false, new TargetPredicate(this))); } - @Override - protected void entityInit() - { - super.entityInit(); - this.dataManager.register(TAMED, Byte.valueOf((byte) 0)); - this.dataManager.register(OWNER_UNIQUE_ID, Optional.absent()); - } - @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); - this.getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(40.0D); getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D); getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.27D); } + @Override public void setCombatTask() { if (this.worldObj != null && !this.worldObj.isRemote) @@ -301,20 +276,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna return arrowEffects; } - @Override - public void onLivingUpdate() - { - this.updateArmSwingProgress(); - float f = this.getBrightness(1.0F); - - if (f > 0.5F) - { - this.entityAge += 2; - } - - super.onLivingUpdate(); - } - @Override public boolean attackEntityFrom(DamageSource source, float amount) { @@ -327,53 +288,7 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna @Override public boolean attackEntityAsMob(Entity attackedEntity) { - float f = (float) this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue(); - int i = 0; - - if (attackedEntity instanceof EntityLivingBase) - { - f += EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((EntityLivingBase) attackedEntity).getCreatureAttribute()); - i += EnchantmentHelper.getKnockbackModifier(this); - } - - boolean flag = attackedEntity.attackEntityFrom(DamageSource.causeMobDamage(this), f); - - if (flag) - { - if (i > 0 && attackedEntity instanceof EntityLivingBase) - { - ((EntityLivingBase) attackedEntity).knockBack(this, (float) i * 0.5F, (double) MathHelper.sin(this.rotationYaw * 0.017453292F), (double) (-MathHelper.cos(this.rotationYaw * 0.017453292F))); - this.motionX *= 0.6D; - this.motionZ *= 0.6D; - } - - int j = EnchantmentHelper.getFireAspectModifier(this); - - if (j > 0) - { - attackedEntity.setFire(j * 4); - } - - if (attackedEntity instanceof EntityPlayer) - { - EntityPlayer entityplayer = (EntityPlayer) attackedEntity; - ItemStack itemstack = this.getHeldItemMainhand(); - ItemStack itemstack1 = entityplayer.isHandActive() ? entityplayer.getActiveItemStack() : null; - - if (itemstack != null && itemstack1 != null && itemstack.getItem() instanceof ItemAxe && itemstack1.getItem() == Items.SHIELD) - { - float f1 = 0.25F + (float) EnchantmentHelper.getEfficiencyModifier(this) * 0.05F; - - if (this.rand.nextFloat() < f1) - { - entityplayer.getCooldownTracker().setCooldown(Items.SHIELD, 100); - this.worldObj.setEntityState(entityplayer, (byte) 30); - } - } - } - - this.applyEnchantments(this, attackedEntity); - } + boolean flag = super.attackEntityAsMob(attackedEntity); if (flag) { @@ -390,17 +305,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna } } - @Override - public void setItemStackToSlot(EntityEquipmentSlot slotIn, ItemStack stack) - { - super.setItemStackToSlot(slotIn, stack); - - if (!this.worldObj.isRemote && slotIn == EntityEquipmentSlot.MAINHAND) - { - this.setCombatTask(); - } - } - @Override public void onDeath(DamageSource cause) { @@ -412,11 +316,13 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna } } + @Override public boolean isStationary() { return false; } + @Override public boolean absorbExplosion(Explosion explosion) { if (this.type == EnumDemonWillType.DESTRUCTIVE) @@ -468,19 +374,16 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna return super.isEntityInvulnerable(source) && (this.type == EnumDemonWillType.DESTRUCTIVE && source.isExplosion()); } + @Override public void performEmergencyHeal(double toHeal) { this.heal((float) toHeal); -// double d0 = this.rand.nextGaussian() * 0.02D; -// double d1 = this.rand.nextGaussian() * 0.02D; -// double d2 = this.rand.nextGaussian() * 0.02D; if (worldObj instanceof WorldServer) { WorldServer server = (WorldServer) worldObj; server.spawnParticle(EnumParticleTypes.HEART, this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height), this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, 7, 0.2, 0.2, 0.2, 0, new int[0]); } -// this.worldObj.spawnParticle(EnumParticleTypes.HEART, this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height), this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, d0, d1, d2, new int[0]); } /** @@ -513,11 +416,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna return 0; } - public boolean shouldSelfHeal() - { - return this.getHealth() < this.getMaxHealth() * 0.5; - } - public double getWillToHealth() { return 2; @@ -544,14 +442,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna { super.writeEntityToNBT(tag); - if (this.getOwnerId() == null) - { - tag.setString("OwnerUUID", ""); - } else - { - tag.setString("OwnerUUID", this.getOwnerId().toString()); - } - tag.setString(Constants.NBT.WILL_TYPE, type.toString()); tag.setBoolean("sentientArmour", wasGivenSentientArmour); @@ -562,29 +452,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna { super.readEntityFromNBT(tag); - String s = ""; - - if (tag.hasKey("OwnerUUID", 8)) - { - s = tag.getString("OwnerUUID"); - } else - { - String s1 = tag.getString("Owner"); - s = PreYggdrasilConverter.convertMobOwnerIfNeeded(this.getServer(), s1); - } - - if (!s.isEmpty()) - { - try - { - this.setOwnerId(UUID.fromString(s)); - this.setTamed(true); - } catch (Throwable var4) - { - this.setTamed(false); - } - } - if (!tag.hasKey(Constants.NBT.WILL_TYPE)) { type = EnumDemonWillType.DEFAULT; @@ -599,27 +466,19 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna } //TODO: Change to fit the given AI + @Override public boolean shouldAttackEntity(EntityLivingBase attacker, EntityLivingBase owner) { if (!(attacker instanceof EntityCreeper) && !(attacker instanceof EntityGhast)) { - if (attacker instanceof IEntityOwnable) - { - IEntityOwnable entityOwnable = (IEntityOwnable) attacker; - - if (entityOwnable.getOwner() == owner) - { - return false; - } - } - - return attacker instanceof EntityPlayer && owner instanceof EntityPlayer && !((EntityPlayer) owner).canAttackPlayer((EntityPlayer) attacker) ? false : !(attacker instanceof EntityHorse) || !((EntityHorse) attacker).isTame(); + return super.shouldAttackEntity(attacker, owner); } else { return false; } } + @Override public void attackEntityWithRangedAttack(EntityLivingBase target, float velocity) { ItemStack heldStack = this.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND); @@ -677,26 +536,6 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna } } - public boolean isTamed() - { - return (((Byte) this.dataManager.get(TAMED)).byteValue() & 4) != 0; - } - - public void setTamed(boolean tamed) - { - byte b0 = ((Byte) this.dataManager.get(TAMED)).byteValue(); - - if (tamed) - { - this.dataManager.set(TAMED, Byte.valueOf((byte) (b0 | 4))); - } else - { - this.dataManager.set(TAMED, Byte.valueOf((byte) (b0 & -5))); - } - -// this.setupTamedAI(); - } - @Override protected SoundEvent getAmbientSound() { @@ -729,49 +568,4 @@ public class EntitySentientSpecter extends EntityCreature implements IEntityOwna { return 0.4F; } - - @Override - public UUID getOwnerId() - { - return (UUID) (this.dataManager.get(OWNER_UNIQUE_ID)).orNull(); - } - - public void setOwnerId(UUID uuid) - { - this.dataManager.set(OWNER_UNIQUE_ID, Optional.fromNullable(uuid)); - } - - @Override - public EntityLivingBase getOwner() - { - try - { - UUID uuid = this.getOwnerId(); - return uuid == null ? null : this.worldObj.getPlayerEntityByUUID(uuid); - } catch (IllegalArgumentException var2) - { - return null; - } - } - - public void setOwner(EntityPlayer player) - { - setOwnerId(player.getUniqueID()); - } - - public class TargetPredicate implements Predicate - { - EntitySentientSpecter entity; - - public TargetPredicate(EntitySentientSpecter entity) - { - this.entity = entity; - } - - @Override - public boolean apply(EntityMob input) - { - return entity.shouldAttackEntity(input, this.entity.getOwner()); - } - } } \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/tile/TileMimic.java b/src/main/java/WayofTime/bloodmagic/tile/TileMimic.java index 33f8e993..7d00a2a7 100644 --- a/src/main/java/WayofTime/bloodmagic/tile/TileMimic.java +++ b/src/main/java/WayofTime/bloodmagic/tile/TileMimic.java @@ -256,7 +256,7 @@ public class TileMimic extends TileInventory implements ITickable EntityMimic mimicEntity = new EntityMimic(worldObj); mimicEntity.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); - mimicEntity.initializeMimic(getStackInSlot(0), tileTag, dropItemsOnBreak, metaOfReplacedBlock, playerCheckRadius); + mimicEntity.initializeMimic(getStackInSlot(0), tileTag, dropItemsOnBreak, metaOfReplacedBlock, playerCheckRadius, pos); tileTag = null; mimicedTile = null; this.setInventorySlotContents(0, null);