OrcaWorld Posted November 1, 2020 Posted November 1, 2020 Heyo everyone. Today I made Phantom's AI like entity , but for some reason it doesn't spawn. Maybe some of you knows how to fix it? AI: package com.orca.moles; import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityPredicate; import net.minecraft.entity.EntitySize; import net.minecraft.entity.EntityType; import net.minecraft.entity.FlyingEntity; import net.minecraft.entity.ILivingEntityData; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.Pose; import net.minecraft.entity.SpawnReason; import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.controller.BodyController; import net.minecraft.entity.ai.controller.LookController; import net.minecraft.entity.ai.controller.MovementController; import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.monster.PhantomEntity; import net.minecraft.entity.passive.AmbientEntity; import net.minecraft.entity.passive.CatEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityPredicates; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; import net.minecraft.world.gen.Heightmap; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import javax.annotation.Nullable; import java.util.Comparator; import java.util.EnumSet; import java.util.List; public class EagleEntity extends FlyingEntity implements IMob { private static final DataParameter<Integer> SIZE = EntityDataManager.createKey(EagleEntity.class, DataSerializers.VARINT); private Vector3d orbitOffset = Vector3d.ZERO; private BlockPos orbitPosition = BlockPos.ZERO; private EagleEntity.AttackPhase attackPhase = EagleEntity.AttackPhase.CIRCLE; public EagleEntity(EntityType<? extends EagleEntity> type, World worldIn) { super(type, worldIn); this.moveController = new MoveHelperController(this); this.lookController = new LookHelperController(this); } protected BodyController createBodyController() { return new EagleEntity.BodyHelperController(this); } protected void registerGoals() { this.goalSelector.addGoal(1, new EagleEntity.PickAttackGoal()); this.goalSelector.addGoal(2, new EagleEntity.SweepAttackGoal()); this.goalSelector.addGoal(3, new EagleEntity.OrbitPointGoal()); this.targetSelector.addGoal(1, new EagleEntity.AttackMoleGoal()); } protected void registerData() { super.registerData(); this.dataManager.register(SIZE, 0); } public void setPhantomSize(int sizeIn) { this.dataManager.set(SIZE, MathHelper.clamp(sizeIn, 1, 1)); } private void updatePhantomSize() { this.recalculateSize(); this.getAttribute(Attributes.field_233823_f_).setBaseValue((double)(1 + this.getPhantomSize())); } public int getPhantomSize() { return this.dataManager.get(SIZE); } protected float getStandingEyeHeight(Pose poseIn, EntitySize sizeIn) { return sizeIn.height * 1F; } public void notifyDataManagerChange(DataParameter<?> key) { if (SIZE.equals(key)) { this.updatePhantomSize(); } super.notifyDataManagerChange(key); } protected boolean isDespawnPeaceful() { return false; } /** * Called to update the entity's position/logic. */ public void tick() { super.tick(); if (this.world.isRemote) { float f = MathHelper.cos((float)(this.getEntityId() * 3 + this.ticksExisted) * 0.13F + (float)Math.PI); float f1 = MathHelper.cos((float)(this.getEntityId() * 3 + this.ticksExisted + 1) * 0.13F + (float)Math.PI); if (f > 0.0F && f1 <= 0.0F) { this.world.playSound(this.getPosX(), this.getPosY(), this.getPosZ(), SoundEvents.ENTITY_PHANTOM_FLAP, this.getSoundCategory(), 0.95F + this.rand.nextFloat() * 0.05F, 0.95F + this.rand.nextFloat() * 0.05F, false); } int i = this.getPhantomSize(); float f2 = MathHelper.cos(this.rotationYaw * ((float)Math.PI / 180F)) * (1.3F + 0.21F * (float)i); float f3 = MathHelper.sin(this.rotationYaw * ((float)Math.PI / 180F)) * (1.3F + 0.21F * (float)i); float f4 = (0.3F + f * 0.45F) * ((float)i * 0.2F + 1.0F); this.world.addParticle(ParticleTypes.MYCELIUM, this.getPosX() + (double)f2, this.getPosY() + (double)f4, this.getPosZ() + (double)f3, 0.0D, 0.0D, 0.0D); this.world.addParticle(ParticleTypes.MYCELIUM, this.getPosX() - (double)f2, this.getPosY() + (double)f4, this.getPosZ() - (double)f3, 0.0D, 0.0D, 0.0D); } } /** * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons * use this to react to sunlight and start to burn. */ public void livingTick() { if (this.isAlive() && this.isInDaylight()) { this.setFire(0); } super.livingTick(); } protected void updateAITasks() { super.updateAITasks(); } public ILivingEntityData onInitialSpawn(IServerWorld worldIn, DifficultyInstance difficultyIn, SpawnReason reason, @Nullable ILivingEntityData spawnDataIn, @Nullable CompoundNBT dataTag) { this.orbitPosition = this.func_233580_cy_().up(5); this.setPhantomSize(1); return super.onInitialSpawn(worldIn, difficultyIn, reason, spawnDataIn, dataTag); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ public void readAdditional(CompoundNBT compound) { super.readAdditional(compound); if (compound.contains("AX")) { this.orbitPosition = new BlockPos(compound.getInt("AX"), compound.getInt("AY"), compound.getInt("AZ")); } this.setPhantomSize(compound.getInt("Size")); } public void writeAdditional(CompoundNBT compound) { super.writeAdditional(compound); compound.putInt("AX", this.orbitPosition.getX()); compound.putInt("AY", this.orbitPosition.getY()); compound.putInt("AZ", this.orbitPosition.getZ()); compound.putInt("Size", this.getPhantomSize()); } /** * Checks if the entity is in range to render. */ @OnlyIn(Dist.CLIENT) public boolean isInRangeToRenderDist(double distance) { return true; } public SoundCategory getSoundCategory() { return SoundCategory.HOSTILE; } protected SoundEvent getAmbientSound() { return SoundsInit.ENTITY_EAGLE_AMBIENT.get(); } protected SoundEvent getHurtSound(DamageSource damageSourceIn) { return SoundsInit.ENTITY_EAGLE_HURT.get(); } protected SoundEvent getDeathSound() { return SoundsInit.ENTITY_EAGLE_DEATH.get(); } public CreatureAttribute getCreatureAttribute() { return CreatureAttribute.UNDEAD; } /** * Returns the volume for the sounds this mob makes. */ protected float getSoundVolume() { return 1.0F; } public boolean canAttack(EntityType<?> typeIn) { return true; } public EntitySize getSize(Pose poseIn) { int i = this.getPhantomSize(); EntitySize entitysize = super.getSize(poseIn); float f = (entitysize.width + 0.2F * (float)i) / entitysize.width; return entitysize.scale(f); } static enum AttackPhase { CIRCLE, SWOOP; } class AttackMoleGoal extends Goal { private final EntityPredicate field_220842_b = (new EntityPredicate()).setDistance(64.0D); private int tickDelay = 20; private AttackMoleGoal() { } /** * Returns whether execution should begin. You can also read and cache any state necessary for execution in this * method as well. */ public boolean shouldExecute() { if (this.tickDelay > 0) { --this.tickDelay; return false; } else { this.tickDelay = 60; BlockPos blockpos; List<PlayerEntity> list = EagleEntity.this.world.getTargettablePlayersWithinAABB(this.field_220842_b, EagleEntity.this, EagleEntity.this.getBoundingBox().grow(16.0D, 64.0D, 16.0D)); if (!list.isEmpty()) { list.sort(Comparator.<Entity, Double>comparing(Entity::getPosY).reversed()); for(PlayerEntity playerentity : list) { if (EagleEntity.this.canAttack(playerentity, EntityPredicate.DEFAULT)) { EagleEntity.this.setAttackTarget(playerentity); return true; } } } return false; } } /** * Returns whether an in-progress EntityAIBase should continue executing */ public boolean shouldContinueExecuting() { LivingEntity livingentity = EagleEntity.this.getAttackTarget(); return livingentity != null ? EagleEntity.this.canAttack(livingentity, EntityPredicate.DEFAULT) : false; } } class BodyHelperController extends BodyController { public BodyHelperController(MobEntity mob) { super(mob); } /** * Update the Head and Body rendenring angles */ public void updateRenderAngles() { EagleEntity.this.rotationYawHead = EagleEntity.this.renderYawOffset; EagleEntity.this.renderYawOffset = EagleEntity.this.rotationYaw; } } class LookHelperController extends LookController { public LookHelperController(MobEntity entityIn) { super(entityIn); } /** * Updates look */ public void tick() { } } abstract class MoveGoal extends Goal { public MoveGoal() { this.setMutexFlags(EnumSet.of(Goal.Flag.MOVE)); } protected boolean func_203146_f() { return EagleEntity.this.orbitOffset.squareDistanceTo(EagleEntity.this.getPosX(), EagleEntity.this.getPosY(), EagleEntity.this.getPosZ()) < 4.0D; } } class MoveHelperController extends MovementController { private float speedFactor = 0.1F; public MoveHelperController(MobEntity entityIn) { super(entityIn); } public void tick() { if (EagleEntity.this.collidedHorizontally) { EagleEntity.this.rotationYaw += 180.0F; this.speedFactor = 0.1F; } float f = (float)(EagleEntity.this.orbitOffset.x - EagleEntity.this.getPosX()); float f1 = (float)(EagleEntity.this.orbitOffset.y - EagleEntity.this.getPosY()); float f2 = (float)(EagleEntity.this.orbitOffset.z - EagleEntity.this.getPosZ()); double d0 = (double)MathHelper.sqrt(f * f + f2 * f2); double d1 = 1.0D - (double)MathHelper.abs(f1 * 0.7F) / d0; f = (float)((double)f * d1); f2 = (float)((double)f2 * d1); d0 = (double)MathHelper.sqrt(f * f + f2 * f2); double d2 = (double)MathHelper.sqrt(f * f + f2 * f2 + f1 * f1); float f3 = EagleEntity.this.rotationYaw; float f4 = (float)MathHelper.atan2((double)f2, (double)f); float f5 = MathHelper.wrapDegrees(EagleEntity.this.rotationYaw + 90.0F); float f6 = MathHelper.wrapDegrees(f4 * (180F / (float)Math.PI)); EagleEntity.this.rotationYaw = MathHelper.approachDegrees(f5, f6, 4.0F) - 90.0F; EagleEntity.this.renderYawOffset = EagleEntity.this.rotationYaw; if (MathHelper.degreesDifferenceAbs(f3, EagleEntity.this.rotationYaw) < 3.0F) { this.speedFactor = MathHelper.approach(this.speedFactor, 1.8F, 0.005F * (1.8F / this.speedFactor)); } else { this.speedFactor = MathHelper.approach(this.speedFactor, 0.2F, 0.025F); } float f7 = (float)(-(MathHelper.atan2((double)(-f1), d0) * (double)(180F / (float)Math.PI))); EagleEntity.this.rotationPitch = f7; float f8 = EagleEntity.this.rotationYaw + 90.0F; double d3 = (double)(this.speedFactor * MathHelper.cos(f8 * ((float)Math.PI / 180F))) * Math.abs((double)f / d2); double d4 = (double)(this.speedFactor * MathHelper.sin(f8 * ((float)Math.PI / 180F))) * Math.abs((double)f2 / d2); double d5 = (double)(this.speedFactor * MathHelper.sin(f7 * ((float)Math.PI / 180F))) * Math.abs((double)f1 / d2); Vector3d vector3d = EagleEntity.this.getMotion(); EagleEntity.this.setMotion(vector3d.add((new Vector3d(d3, d5, d4)).subtract(vector3d).scale(0.2D))); } } class OrbitPointGoal extends EagleEntity.MoveGoal { private float field_203150_c; private float field_203151_d; private float field_203152_e; private float field_203153_f; private OrbitPointGoal() { } /** * Returns whether execution should begin. You can also read and cache any state necessary for execution in this * method as well. */ public boolean shouldExecute() { return EagleEntity.this.getAttackTarget() == null || EagleEntity.this.attackPhase == EagleEntity.AttackPhase.CIRCLE; } /** * Execute a one shot task or start executing a continuous task */ public void startExecuting() { this.field_203151_d = 5.0F + EagleEntity.this.rand.nextFloat() * 10.0F; this.field_203152_e = -4.0F + EagleEntity.this.rand.nextFloat() * 9.0F; this.field_203153_f = EagleEntity.this.rand.nextBoolean() ? 1.0F : -1.0F; this.func_203148_i(); } /** * Keep ticking a continuous task that has already been started */ public void tick() { if (EagleEntity.this.rand.nextInt(350) == 0) { this.field_203152_e = -4.0F + EagleEntity.this.rand.nextFloat() * 9.0F; } if (EagleEntity.this.rand.nextInt(250) == 0) { ++this.field_203151_d; if (this.field_203151_d > 15.0F) { this.field_203151_d = 5.0F; this.field_203153_f = -this.field_203153_f; } } if (EagleEntity.this.rand.nextInt(450) == 0) { this.field_203150_c = EagleEntity.this.rand.nextFloat() * 2.0F * (float)Math.PI; this.func_203148_i(); } if (this.func_203146_f()) { this.func_203148_i(); } if (EagleEntity.this.orbitOffset.y < EagleEntity.this.getPosY() && !EagleEntity.this.world.isAirBlock(EagleEntity.this.func_233580_cy_().down(1))) { this.field_203152_e = Math.max(1.0F, this.field_203152_e); this.func_203148_i(); } if (EagleEntity.this.orbitOffset.y > EagleEntity.this.getPosY() && !EagleEntity.this.world.isAirBlock(EagleEntity.this.func_233580_cy_().up(1))) { this.field_203152_e = Math.min(-1.0F, this.field_203152_e); this.func_203148_i(); } } private void func_203148_i() { if (BlockPos.ZERO.equals(EagleEntity.this.orbitPosition)) { EagleEntity.this.orbitPosition = EagleEntity.this.func_233580_cy_(); } this.field_203150_c += this.field_203153_f * 15.0F * ((float)Math.PI / 180F); EagleEntity.this.orbitOffset = Vector3d.func_237491_b_(EagleEntity.this.orbitPosition).add((double)(this.field_203151_d * MathHelper.cos(this.field_203150_c)), (double)(-4.0F + this.field_203152_e), (double)(this.field_203151_d * MathHelper.sin(this.field_203150_c))); } } class PickAttackGoal extends Goal { private int tickDelay; private PickAttackGoal() { } /** * Returns whether execution should begin. You can also read and cache any state necessary for execution in this * method as well. */ public boolean shouldExecute() { LivingEntity livingentity = EagleEntity.this.getAttackTarget(); return livingentity != null ? EagleEntity.this.canAttack(EagleEntity.this.getAttackTarget(), EntityPredicate.DEFAULT) : false; } /** * Execute a one shot task or start executing a continuous task */ public void startExecuting() { this.tickDelay = 10; EagleEntity.this.attackPhase = EagleEntity.AttackPhase.CIRCLE; this.func_203143_f(); } /** * Reset the task's internal state. Called when this task is interrupted by another one */ public void resetTask() { EagleEntity.this.orbitPosition = EagleEntity.this.world.getHeight(Heightmap.Type.MOTION_BLOCKING, EagleEntity.this.orbitPosition).up(10 + EagleEntity.this.rand.nextInt(20)); } /** * Keep ticking a continuous task that has already been started */ public void tick() { if (EagleEntity.this.attackPhase == EagleEntity.AttackPhase.CIRCLE) { --this.tickDelay; if (this.tickDelay <= 0) { EagleEntity.this.attackPhase = EagleEntity.AttackPhase.SWOOP; this.func_203143_f(); this.tickDelay = (8 + EagleEntity.this.rand.nextInt(4)) * 20; EagleEntity.this.playSound(SoundsInit.ENTITY_EAGLE_ATTACK.get(), 10.0F, 0.95F + EagleEntity.this.rand.nextFloat() * 0.1F); } } } private void func_203143_f() { EagleEntity.this.orbitPosition = EagleEntity.this.getAttackTarget().func_233580_cy_().up(20 + EagleEntity.this.rand.nextInt(20)); if (EagleEntity.this.orbitPosition.getY() < EagleEntity.this.world.getSeaLevel()) { EagleEntity.this.orbitPosition = new BlockPos(EagleEntity.this.orbitPosition.getX(), EagleEntity.this.world.getSeaLevel() + 1, EagleEntity.this.orbitPosition.getZ()); } } } class SweepAttackGoal extends EagleEntity.MoveGoal { private SweepAttackGoal() { } /** * Returns whether execution should begin. You can also read and cache any state necessary for execution in this * method as well. */ public boolean shouldExecute() { return EagleEntity.this.getAttackTarget() != null && EagleEntity.this.attackPhase == EagleEntity.AttackPhase.SWOOP; } /** * Returns whether an in-progress EntityAIBase should continue executing */ public boolean shouldContinueExecuting() { LivingEntity livingentity = EagleEntity.this.getAttackTarget(); if (livingentity == null) { return false; } else if (!livingentity.isAlive()) { return false; } else if (!(livingentity instanceof PlayerEntity) || !((PlayerEntity)livingentity).isSpectator() && !((PlayerEntity)livingentity).isCreative()) { if (!this.shouldExecute()) { return false; } else { if (EagleEntity.this.ticksExisted % 20 == 0) { List<CatEntity> list = EagleEntity.this.world.getEntitiesWithinAABB(CatEntity.class, EagleEntity.this.getBoundingBox().grow(16.0D), EntityPredicates.IS_ALIVE); if (!list.isEmpty()) { for(CatEntity catentity : list) { catentity.func_213420_ej(); } return false; } } return true; } } else { return false; } } /** * Execute a one shot task or start executing a continuous task */ public void startExecuting() { } /** * Reset the task's internal state. Called when this task is interrupted by another one */ public void resetTask() { EagleEntity.this.setAttackTarget((LivingEntity)null); EagleEntity.this.attackPhase = EagleEntity.AttackPhase.CIRCLE; } /** * Keep ticking a continuous task that has already been started */ public void tick() { LivingEntity livingentity = EagleEntity.this.getAttackTarget(); EagleEntity.this.orbitOffset = new Vector3d(livingentity.getPosX(), livingentity.getPosYHeight(0.5D), livingentity.getPosZ()); if (EagleEntity.this.getBoundingBox().grow((double)0.2F).intersects(livingentity.getBoundingBox())) { EagleEntity.this.attackEntityAsMob(livingentity); EagleEntity.this.attackPhase = EagleEntity.AttackPhase.CIRCLE; if (!EagleEntity.this.isSilent()) { EagleEntity.this.world.playEvent(1039, EagleEntity.this.func_233580_cy_(), 0); } } else if (EagleEntity.this.collidedHorizontally || EagleEntity.this.hurtTime > 0) { EagleEntity.this.attackPhase = EagleEntity.AttackPhase.CIRCLE; } } } } Mod's main core: package com.orca.moles; import net.minecraft.block.Blocks; import net.minecraft.entity.ai.attributes.GlobalEntityTypeAttributes; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.DeferredWorkQueue; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @Mod("moles") public class MolesMain { private static final Logger LOGGER = LogManager.getLogger(); public static final String MOD_ID = "moles"; public MolesMain() { FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff); SoundsInit.SOUNDS.register(FMLJavaModLoadingContext.get().getModEventBus()); ItemsInit.ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); EntityInit.ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus()); MinecraftForge.EVENT_BUS.register(this); } private void setup(final FMLCommonSetupEvent event) { } private void doClientStuff(final FMLClientSetupEvent event) { DeferredWorkQueue.runLater(() -> { GlobalEntityTypeAttributes.put(EntityInit.MOLE.get(), MoleEntity.func_234233_eS_().func_233813_a_()); GlobalEntityTypeAttributes.put(EntityInit.EAGLE.get(), EagleEntity.func_233666_p_().func_233813_a_()); }); } } Quote
ChampionAsh5357 Posted November 2, 2020 Posted November 2, 2020 7 hours ago, OrcaWorld said: but for some reason it doesn't spawn It would be better if you could provided the log of the error or a more specific explanation of spawning. Do you mean manually through a command or specifically in the world? Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.