lordlogo2002 6b95a3891f Refactor imports and improve code organization across multiple classes
- Reordered and grouped import statements in various files for better readability.
- Removed unnecessary imports and cleaned up unused code.
- Simplified constructors and methods in several classes to enhance clarity.
- Standardized formatting and spacing for consistency throughout the codebase.
- Ensured that all necessary imports are included where required, particularly in structure-related classes.
2025-12-25 16:34:58 +01:00

220 lines
6.8 KiB
Java

package net.Chipperfluff.chipi.entity;
import net.minecraft.block.BlockState;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.goal.*;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.PathAwareEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.property.Properties;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.Chipperfluff.chipi.armor.ProtectionAuraHandler;
import net.Chipperfluff.chipi.item.ModItems;
import net.Chipperfluff.chipi.sound.ModSounds;
import net.Chipperfluff.chipi.util.TickScheduler;
public class MepEntity extends PathAwareEntity {
private static final int FORGET_TARGET_AFTER_TICKS = 100;
private static final int DESPAWN_DISTANCE = 300;
private boolean angryAtPlayer = false;
private int ticksSinceLastSeen = 0;
public MepEntity(EntityType<? extends PathAwareEntity> entityType, World world) {
super(entityType, world);
}
// === AI ===
@Override
protected void initGoals() {
this.goalSelector.add(1, new SwimGoal(this));
this.goalSelector.add(2, new MeleeAttackGoal(this, 1.2D, true));
this.goalSelector.add(3, new WanderAroundFarGoal(this, 1.0D));
this.goalSelector.add(4, new LookAtEntityGoal(this, PlayerEntity.class, 8.0F));
this.goalSelector.add(5, new LookAroundGoal(this));
this.targetSelector.add(
1,
new ActiveTargetGoal<>(
this,
PlayerEntity.class,
true,
target -> target instanceof PlayerEntity player
&& !isHardIgnored(player)
)
);
}
public static DefaultAttributeContainer.Builder createMepAttributes() {
return PathAwareEntity.createMobAttributes()
.add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0)
.add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 4.0)
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25)
.add(EntityAttributes.GENERIC_FOLLOW_RANGE, 32.0);
}
// === Combat memory ===
@Override
public boolean damage(DamageSource source, float amount) {
if (source.getAttacker() instanceof PlayerEntity) {
angryAtPlayer = true;
ticksSinceLastSeen = 0;
}
return super.damage(source, amount);
}
// === ATTACK OVERRIDE (AURA IMMUNITY) ===
@Override
public boolean tryAttack(Entity target) {
if (target instanceof PlayerEntity player) {
if (ProtectionAuraHandler.hasAura(player)) {
return false; // chase but never hit
}
}
return super.tryAttack(target);
}
@Override
public void tick() {
super.tick();
// --- DISTANCE DESPAWN ONLY ---
if (!this.getWorld().isClient && isTooFarFromAllPlayers()) {
this.discard();
return;
}
LivingEntity target = this.getTarget();
if (!(target instanceof PlayerEntity player)) {
angryAtPlayer = false;
ticksSinceLastSeen = 0;
return;
}
if (isHardIgnored(player)) {
clearTarget();
return;
}
if (this.canSee(player)) {
ticksSinceLastSeen = 0;
angryAtPlayer = true;
this.getNavigation().startMovingTo(player, 1.2D);
} else {
ticksSinceLastSeen++;
if (ticksSinceLastSeen <= FORGET_TARGET_AFTER_TICKS) {
this.getNavigation().startMovingTo(player, 1.2D);
} else {
clearTarget();
}
}
}
private void clearTarget() {
angryAtPlayer = false;
ticksSinceLastSeen = 0;
this.setTarget(null);
this.getNavigation().stop();
}
// === DISTANCE CHECK ===
private boolean isTooFarFromAllPlayers() {
double maxSq = DESPAWN_DISTANCE * DESPAWN_DISTANCE;
for (PlayerEntity player : this.getWorld().getPlayers()) {
if (this.squaredDistanceTo(player) <= maxSq) {
return false;
}
}
return true;
}
// === HARD IGNORE RULES ===
private static boolean isHardIgnored(PlayerEntity player) {
if (player.getZ() < 18) return true;
return isOnProtectedBlock(player);
}
private static boolean isOnProtectedBlock(PlayerEntity player) {
BlockPos pos = player.getBlockPos();
BlockState state = player.getWorld().getBlockState(pos);
if (!state.contains(Properties.WATERLOGGED) || !state.get(Properties.WATERLOGGED)) {
return false;
}
return state.getBlock() instanceof StairsBlock
|| state.getBlock() instanceof SlabBlock;
}
// === MILKING ===
@Override
public ActionResult interactMob(PlayerEntity player, Hand hand) {
ItemStack stack = player.getStackInHand(hand);
if (stack.isOf(Items.BUCKET) && !this.isBaby()) {
if (!player.getWorld().isClient) {
stack.decrement(1);
player.giveItemStack(new ItemStack(ModItems.MEP_MILK));
float basePitch = 0.3f + this.random.nextFloat() * 1.9f;
float baseVolume = 0.9f + this.random.nextFloat() * 0.6f;
this.getWorld().playSound(
null,
this.getBlockPos(),
ModSounds.MEP_MILK,
SoundCategory.NEUTRAL,
baseVolume,
basePitch
);
if (this.random.nextFloat() < 0.10f) {
int delay = 10 + this.random.nextInt(21);
float echoPitch = basePitch * 0.5f;
float echoVolume = baseVolume * 0.5f;
TickScheduler.schedule(delay, () -> {
if (!this.isAlive()) return;
this.getWorld().playSound(
null,
this.getBlockPos(),
ModSounds.MEP_MILK,
SoundCategory.NEUTRAL,
echoVolume,
echoPitch
);
});
}
}
return ActionResult.SUCCESS;
}
return super.interactMob(player, hand);
}
}