Posted November 1, 20205 yr 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_()); }); } }
November 2, 20205 yr 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?
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.