Posted November 29, 20231 yr I don't know why my entity can attack any entity but players This is the entity's code package mymod.entities.chicken; import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.Immutable; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.stats.Stats; import net.minecraft.util.RandomSource; import net.minecraft.util.TimeUtil; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.*; import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; import net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal; import net.minecraft.world.entity.animal.*; import net.minecraft.world.entity.monster.Zombie; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import oshi.util.tuples.Pair; import mymod._Entities; import mymod._EntityDataSerializers; import mymod._Items; import mymod._Sounds; import mymod.ai.ZombieAttackChickenEggGoal; import mymod.entities.BredWithMobStorable; import mymod.util.delayedtask.DelayedTask; import mymod.util.delayedtask.DelayedTasksHolder; import java.util.EnumSet; import java.util.Optional; import java.util.UUID; import java.util.function.Supplier; public class Rooster extends AbstractChicken implements NeutralMob, BredWithMobStorable, DelayedTasksHolder<Rooster> { private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(60, 1800); private int remainingPersistentAngerTime; private UUID persistentAngerTarget; private boolean crowing; private int crowTicks; private int diggingAnimTicks; private int featherDropCoolDown; private static final EntityDataAccessor<FourFeathers> DATA_FEATHERS = SynchedEntityData.defineId(Rooster.class, _EntityDataSerializers.ROOSTER_FEATHERS.get()); private static final EntityDataAccessor<Optional<UUID>> DATA_MOB_BRED_WITH = SynchedEntityData.defineId(Rooster.class, EntityDataSerializers.OPTIONAL_UUID); public Rooster(EntityType<? extends Rooster> entityType, Level world) { super(entityType, world); } @Override public int getRemainingPersistentAngerTime() { return remainingPersistentAngerTime; } @Override public void setRemainingPersistentAngerTime(int remainingPersistentAngerTime) { this.remainingPersistentAngerTime = remainingPersistentAngerTime; } @Nullable @Override public UUID getPersistentAngerTarget() { return persistentAngerTarget; } @Override public void setPersistentAngerTarget(@Nullable UUID persistentAngerTarget) { this.persistentAngerTarget = persistentAngerTarget; } @Override public void startPersistentAngerTimer() { setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(random)); } @Override protected void defineSynchedData() { super.defineSynchedData(); entityData.define(DATA_FEATHERS, new FourFeathers((byte) random.nextInt(3), (byte) random.nextInt(3), (byte) random.nextInt(3), (byte) random.nextInt(3))); entityData.define(DATA_MOB_BRED_WITH, Optional.empty()); } public FourFeathers getFeatherData() { return entityData.get(DATA_FEATHERS); } public void setFeatherData(FourFeathers featherData) { entityData.set(DATA_FEATHERS, featherData); } @Override public void addAdditionalSaveData(@NotNull CompoundTag nbt) { super.addAdditionalSaveData(nbt); addPersistentAngerSaveData(nbt); nbt.put("FeatherData", getFeatherData().writeTag()); nbt.putBoolean("isCrowing", crowing); } @Override public void readAdditionalSaveData(@NotNull CompoundTag nbt) { super.readAdditionalSaveData(nbt); readPersistentAngerSaveData(level(), nbt); if (nbt.contains("FeatherData", Tag.TAG_COMPOUND)) setFeatherData(FourFeathers.readTag(nbt.getCompound("FeatherData"))); else setFeatherData(FourFeathers.NONE); crowing = nbt.contains("isCrowing", Tag.TAG_BYTE) && nbt.getBoolean("isCrowing"); } @Override protected void registerGoals() { goalSelector.addGoal(0, new FloatGoal(this)); goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.4, true)); // I even have a MeleeAttackGoal, rooster just runs to player but not hurting him goalSelector.addGoal(1, new RoosterRandomTryFindFoodGoal()); goalSelector.addGoal(2, new RoosterBreedGoal()); goalSelector.addGoal(3, new TemptGoal(this, 1, FOOD_ITEMS, false)); goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1)); goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6)); goalSelector.addGoal(7, new RandomLookAroundGoal(this)); targetSelector.addGoal(4, new RoosterRandomAttackNearbyRoosterGoal()); targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, true, entity -> entity instanceof Fox || (entity instanceof Ocelot ocelot && !ocelot.isBaby()) || (entity instanceof Cat cat && !cat.isBaby() && !cat.isTame()) || (entity instanceof Zombie zombie && zombie.goalSelector .getRunningGoals().anyMatch(wrappedGoal -> wrappedGoal.getGoal() instanceof ZombieAttackChickenEggGoal)) || isAngryAt(entity))); targetSelector.addGoal(2, new HurtByTargetGoal(this)); targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, false)); } @Override public void setMobBredWith(@Nullable UUID uuid) { entityData.set(DATA_MOB_BRED_WITH, Optional.ofNullable(uuid)); } @Override @Nullable public UUID getMobBredWith() { return entityData.get(DATA_MOB_BRED_WITH).orElse(null); } // Goals class RoosterRandomAttackNearbyRoosterGoal extends NearestAttackableTargetGoal<Rooster> { RoosterRandomAttackNearbyRoosterGoal() { super(Rooster.this, Rooster.class, true); } @Override public boolean canUse() { return super.canUse() && random.nextInt(300) == 0; } @Override public boolean canContinueToUse() { return super.canContinueToUse() && mob.getLastHurtMob() != targetMob; } } class RoosterBreedGoal extends BreedGoal { RoosterBreedGoal() { super(Rooster.this, 1, Chicken.class); } @Override protected void breed() { ServerPlayer serverplayer = animal.getLoveCause(); if (serverplayer == null && this.partner.getLoveCause() != null) { serverplayer = this.partner.getLoveCause(); } if (serverplayer != null) { serverplayer.awardStat(Stats.ANIMALS_BRED); CriteriaTriggers.BRED_ANIMALS.trigger(serverplayer, this.animal, this.partner, null); } ((BredWithMobStorable) partner).setMobBredWith(animal.getUUID()); ((BredWithMobStorable) animal).setMobBredWith(partner.getUUID()); animal.setAge(6000); partner.setAge(6000); animal.resetLove(); partner.resetLove(); RandomSource randomsource = animal.getRandom(); if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1)); } } } private static final DelayedTask<Rooster> CROW_LATER = new DelayedTask<>(30) { @Override protected void execute() { entity.crow(); } }; private static final DelayedTask<Rooster> ANGRY_CLUCK_LATER = new DelayedTask<>(30) { @Override protected void execute() { entity.playSound(_Sounds.ROOSTER_ANGRY_CLUCK.get()); } }; @Override public ImmutableList<DelayedTask<Rooster>> getTasks() { return ImmutableList.of(CROW_LATER, ANGRY_CLUCK_LATER); } class RoosterRandomTryFindFoodGoal extends Goal { private final Rooster rooster; private int tickCount; private int maxTickCount; private int lastDugTicks; private int roosterLastHurtByMobTimestamp; private double lookAtXOld, lookAtYOld, lookAtZOld; private Vec3 pos; private boolean didEndSuccessfully; private Vec3 lookingAtPos; private static final UniformInt POSSIBLE_MAX_TICK_COUNT = TimeUtil.rangeOfSeconds(4, 10); RoosterRandomTryFindFoodGoal() { super(); this.rooster = Rooster.this; setFlags(EnumSet.of(Flag.LOOK)); } @Override public boolean canUse() { return (isStandingOn(Blocks.GRASS_BLOCK) || isStandingOn(Blocks.DIRT) || isStandingOn(Blocks.PODZOL)) && rooster.random.nextInt(3000) == 20; } @Override public boolean canContinueToUse() { if (rooster.getLastHurtByMobTimestamp() != roosterLastHurtByMobTimestamp) { didEndSuccessfully = false; return false; } else if (tickCount >= maxTickCount) { didEndSuccessfully = true; return false; } return true; } @Override public boolean requiresUpdateEveryTick() { return true; } @Override public void start() { lastDugTicks = 20; roosterLastHurtByMobTimestamp = rooster.getLastHurtByMobTimestamp(); lookAtXOld = rooster.getLookControl().getWantedX(); lookAtYOld = rooster.getLookControl().getWantedY(); lookAtZOld = rooster.getLookControl().getWantedZ(); pos = new Vec3(rooster.position().toVector3f()); lookingAtPos = rooster.position().subtract(0, 1, 0); rooster.getLookControl().setLookAt(lookingAtPos); maxTickCount = POSSIBLE_MAX_TICK_COUNT.sample(rooster.random); } @Override public void stop() { rooster.getLookControl().setLookAt(lookAtXOld, lookAtYOld, lookAtZOld); if (didEndSuccessfully) { int resultItemPercentage = rooster.random.nextInt(100); if (resultItemPercentage <= 1) { rooster.spawnAtLocation(Items.DIAMOND, -1); Rooster.ANGRY_CLUCK_LATER.startExecution(rooster); } else if (resultItemPercentage <= 5) { rooster.spawnAtLocation(Items.GOLD_NUGGET, -1); Rooster.ANGRY_CLUCK_LATER.startExecution(rooster); } else if (resultItemPercentage <= 20) { Rooster.ANGRY_CLUCK_LATER.startExecution(rooster); } else { rooster.spawnAtLocation(FOOD_ITEMS.getItems()[rooster.random.nextInt( FOOD_ITEMS.getItems().length)], -1); Rooster.CROW_LATER.startExecution(rooster); } } } @Override public void tick() { ++tickCount; rooster.getLookControl().setLookAt(lookingAtPos); rooster.getMoveControl().setWantedPosition(pos.x, pos.y, pos.z, rooster.getMoveControl().getSpeedModifier()); if (lastDugTicks <= 0) { lastDugTicks = 20; rooster.diggingAnimTicks = 10; rooster.playSound(rooster.level().getBlockState(rooster.blockPosition().below()) .getSoundType(rooster.level(), rooster.blockPosition().below(), rooster) .getHitSound()); } else lastDugTicks--; } private boolean isStandingOn(Block block) { return rooster.level().getBlockState(rooster.blockPosition().below()).is(block); } } // Feather data storage @Immutable public record FourFeathers(@NotNull FeatherType first, @NotNull FeatherType second, @NotNull FeatherType third, @NotNull FeatherType forth) { public static final FourFeathers NONE = new FourFeathers(FeatherType.NONE, FeatherType.NONE, FeatherType.NONE, FeatherType.NONE); public FourFeathers(byte first, byte second, byte third, byte forth) { this(FeatherType.fromByte(first), FeatherType.fromByte(second), FeatherType.fromByte(third), FeatherType.fromByte(forth)); } public @NotNull Pair<ItemStack, FourFeathers> removeRandom(RandomSource randomSource) { if (NONE.equals(this)) return new Pair<>(ItemStack.EMPTY, this); int randomNum = randomSource.nextInt(4); while (get(randomNum) == null) randomNum = randomSource.nextInt(4); ItemStack retVal0 = get(randomNum).getDefaultInstance(); FourFeathers retVal1 = switch (randomNum) { case 0 -> new FourFeathers(FeatherType.NONE, second, third, forth); case 1 -> new FourFeathers(first, FeatherType.NONE, third, forth); case 2 -> new FourFeathers(first, second, FeatherType.NONE, forth); case 3 -> new FourFeathers(first, second, third, FeatherType.NONE); default -> null; // unreachable }; return new Pair<>(retVal0, retVal1); } @Nullable public Item get(int i) { return (switch (i) { case 0 -> first; case 1 -> second; case 2 -> third; case 3 -> forth; default -> throw new IllegalStateException("Unexpected value: " + i); }).asItem(); } // NBT Utils @NotNull public CompoundTag writeTag() { CompoundTag nbt = new CompoundTag(); nbt.putString("first", first.name().toLowerCase()); nbt.putString("second", second.name().toLowerCase()); nbt.putString("third", third.name().toLowerCase()); nbt.putString("forth", forth.name().toLowerCase()); return nbt; } @NotNull public static FourFeathers readTag(@NotNull CompoundTag nbt) { return new FourFeathers(tryRead(nbt, "first"), tryRead(nbt, "second"), tryRead(nbt, "third"), tryRead(nbt, "forth")); } private static FeatherType tryRead(CompoundTag tag, String toRead) { if (tag.contains(toRead, Tag.TAG_STRING)) { try { return FeatherType.valueOf(tag.getString(toRead).toUpperCase()); } catch (IllegalArgumentException e) { return FeatherType.NONE; } } return FeatherType.NONE; } } public enum FeatherType implements ItemLike { RED(_Items.RED_FEATHER, (byte) 0), YELLOW(_Items.YELLOW_FEATHER, (byte) 1), GREEN(_Items.GREEN_FEATHER, (byte) 2), BLUE(_Items.BLUE_FEATHER, (byte) 3), NONE(() -> null, (byte) -1); private final Supplier<Item> itemSup; private final byte byteVal; FeatherType(Supplier<Item> itemSup, byte byteVal) { this.itemSup = itemSup; this.byteVal = byteVal; } public static FeatherType fromByte(byte item) { return switch (item) { case -1 -> NONE; case 0 -> RED; case 1 -> YELLOW; case 2 -> GREEN; case 3 -> BLUE; default -> throw new IllegalArgumentException("item: " + item); }; } @Override public @Nullable Item asItem() { return itemSup.get(); } public byte asByte() { return byteVal; } } // Sounds @Override protected SoundEvent getAmbientSound() { return _Sounds.ROOSTER_AMBIENT.get(); } @Override protected SoundEvent getHurtSound(@NotNull DamageSource damageSource) { return _Sounds.ROOSTER_HURT.get(); } @Override protected SoundEvent getDeathSound() { return _Sounds.ROOSTER_DEATH.get(); } public static AttributeSupplier.Builder createAttributes() { // Maybe something's missing here? return createMobAttributes() .add(Attributes.ATTACK_DAMAGE, 2) .add(Attributes.MAX_HEALTH, 8) .add(Attributes.MOVEMENT_SPEED, .3); } @Override public boolean isBaby() { return false; } @Override public boolean canMate(@NotNull Animal other) { if (this == other) return false; else if (!(other instanceof Chicken)) return false; else return isInLove() && other.isInLove(); } @Override protected void doAIStep() { if (!level().isClientSide) { updatePersistentAnger((ServerLevel) level(), true); } } @Override public void setBaby(boolean baby) { if (baby) { Chick me = convertTo(_Entities.CHICK.get(), false); if (me != null) { me.setBoy(true); } } } @Override public @NotNull InteractionResult mobInteract(@NotNull Player player, @NotNull InteractionHand hand) { if (isFood(player.getItemInHand(hand))) { return super.mobInteract(player, hand); } else if (player.getItemInHand(hand) == ItemStack.EMPTY) { dropFeather(player); return InteractionResult.CONSUME; } return InteractionResult.PASS; } private void dropFeather(LivingEntity target) { Pair<ItemStack, FourFeathers> resFeathers = getFeatherData().removeRandom(random); setFeatherData(resFeathers.getB()); if (resFeathers.getA() != null && featherDropCoolDown == 0) { spawnAtLocation(resFeathers.getA()); playSound(SoundEvents.ITEM_PICKUP); setTarget(target); featherDropCoolDown = random.nextIntBetweenInclusive(20, 30); } } @Override public void setTarget(@Nullable LivingEntity target) { super.setTarget(target); if (target != null) { setPersistentAngerTarget(target.getUUID()); startPersistentAngerTimer(); } } public void crow() { if (!crowing) { crowing = true; crowTicks = 70; var lookControl = getLookControl(); lookControl.setLookAt(lookControl.getWantedX(), position().y + .2, lookControl.getWantedZ()); playSound(_Sounds.ROOSTER_CROW.get()); level().getEntitiesOfClass(Chicken.class, getBoundingBox().inflate(20)) .forEach(chicken -> chicken.setTarget(this)); } } public boolean isCrowing() { return crowing; } @Override public void tick() { super.tick(); if (!level().isClientSide) { if (level().getDayTime() == 0L || level().getDayTime() % 24000L == 13000L) crow(); } if (crowing && --crowTicks <= 0) { crowing = false; } if (diggingAnimTicks > 0) --diggingAnimTicks; if (featherDropCoolDown > 0) --featherDropCoolDown; tickTasks(); } public int getDiggingAnimTicks() { return diggingAnimTicks; } @Override public boolean isBoy() { return true; } }
November 29, 20231 yr While I cannot pinpoint what is preventing the rooster from damaging the player, try using a debugger and set a breakpoint in the MeleeAttackGoal class--in the tick() and/or checkAndPerformAttack() methods.
November 30, 20231 yr Author 13 hours ago, LeeCrafts said: While I cannot pinpoint what is preventing the rooster from damaging the player, try using a debugger and set a breakpoint in the MeleeAttackGoal class--in the tick() and/or checkAndPerformAttack() methods. is the breakpoint saved when I create a .jar?
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.