package playasmob;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.projectile.LargeFireball;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.monster.Ghast;
import net.minecraft.world.entity.monster.Enemy;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.tags.DamageTypeTags;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.resources.ResourceKey;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.client.renderer.entity.state.GhastRenderState;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.entity.GhastRenderer;
import net.minecraft.client.renderer.entity.EntityRenderer;
import java.util.List;
public class GhastInfo extends FlyingMobInfo implements Enemy {
public static final Synched chargeTime = Synched.ChargeTime;
public static final Synched charge = Synched.Charge;
public static final Synched firing = Synched.Firing;
public int explosionPower = 1;
public GhastInfo(Player player, CompoundTag compound) {
super(EntityType.GHAST, Ghast.class, player, compound);
}
public GhastInfo(Player player) {
this(player, null);
}
public GhastInfo() {
this(null);
}
// Custom Code
@Override
public void reset() {
super.reset();
this.reset(chargeTime);
this.reset(charge);
this.reset(firing);
}
@Override
public EntityRenderer getRenderer() {
return new GhastRenderer(Utils.getContext());
}
@Override
public EntityRenderState createState() {
return new GhastRenderState();
}
@Override
public void modifyState(EntityRenderState state) {
super.modifyState(state);
if (state instanceof GhastRenderState ghastState)
ghastState.isCharging = this.isCharging();
}
@Override
public void press(int key, boolean pressed, int time) {
if (key == 1)
this.set(firing, pressed);
}
@Override
public List<HudIcon> getIcons(float partialTick) {
if(this.isSpectator())
return super.getIcons(partialTick);
int cooldown = Math.max((this.<Integer>get(chargeTime) * -1) / 20, 0);
HudIcon attack = new HudIcon("textures/item/fire_charge.png").key(Keybinds.Key1).using(this.get(firing)).useable(cooldown == 0).countdown(cooldown);
return Utils.merge(super.getIcons(partialTick), List.of(attack));
}
@Override
public float getMaxHeadRotationRelativeToBody(float original) {
return 0;
}
@Override
public boolean serverAiStep(Object object) {
if (!super.serverAiStep(null))
return false;
if (this.isClient() || this.isSpectator())
return true;
int time = this.get(chargeTime);
if (time < 0 || this.<Boolean>get(firing))
this.set(chargeTime, time + 1);
if (!this.<Boolean>get(firing)) {
if (time > 0)
this.set(chargeTime, time - 1);
this.setCharging(time > 10);
return true;
}
if (time == 10 && !this.isSilent())
this.level().levelEvent(null, 1015, this.blockPosition(), 0);
if (time == 20) {
if (!this.isSilent())
this.level().levelEvent(null, 1016, this.blockPosition(), 0);
Vec3 viewPoint = this.getViewVector(1);
LargeFireball fireball = new LargeFireball(this.level(), this.player, Utils.getFacingImpluse(this.player).normalize(), this.getExplosionPower());
fireball.setPos(this.getX() + viewPoint.x * 4.0, this.getY(0.5) + 0.5, fireball.getZ() + viewPoint.z * 4.0);
this.level().addFreshEntity(fireball);
this.set(chargeTime, -40);
}
this.setCharging(time > 10);
return true;
}
@Override
public ResourceKey<Level> getRespawnDimension() {
return Level.NETHER;
}
@Override
public List<ResourceKey<Biome>> getRespawnBiomes(ResourceKey<Level> dimension) {
return dimension.equals(Level.NETHER) ? List.of(Biomes.BASALT_DELTAS, Biomes.NETHER_WASTES, Biomes.SOUL_SAND_VALLEY) : super.getRespawnBiomes(dimension);
}
// Ghast.class Code
public boolean isCharging() {
return this.get(charge);
}
public void setCharging(boolean charging) {
this.set(charge, charging);
}
public int getExplosionPower() {
return this.explosionPower + 1;
}
public boolean isReflectedFireball(DamageSource source) {
return source.getDirectEntity() instanceof LargeFireball && source.getEntity() instanceof Player player && !player.equals(this.player);
}
@Override
public boolean isInvulnerableTo(boolean original, ServerLevel server, DamageSource source) {
return this.isInvulnerable() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) || !isReflectedFireball(source) && super.isInvulnerableTo(original, server, source);
}
@Override
public boolean hurtServer(boolean original, ServerLevel server, DamageSource source, float damage) {
if (this.isReflectedFireball(source))
return super.hurtServer(original, server, source, 1000);
return this.isInvulnerableTo(server, source) ? false : super.hurtServer(original, server, source, damage);
}
@Override
public SoundSource getSoundSource() {
return SoundSource.HOSTILE;
}
@Override
public SoundEvent getAmbientSound() {
return SoundEvents.GHAST_AMBIENT;
}
@Override
public SoundEvent getHurtSound(SoundEvent original, DamageSource source) {
return SoundEvents.GHAST_HURT;
}
@Override
public SoundEvent getDeathSound(SoundEvent original) {
return SoundEvents.GHAST_DEATH;
}
@Override
public float getSoundVolume(float original) {
return 5;
}
@Override
public CompoundTag saveData() {
CompoundTag compound = super.saveData();
compound.putByte("ExplosionPower", (byte) this.explosionPower);
return compound;
}
@Override
public void loadData(CompoundTag compound) {
super.loadData(compound);
if (compound.contains("ExplosionPower", 99))
this.explosionPower = compound.getByte("ExplosionPower");
}
}