Source CreeperInfo - Spiderman31807/Mob_Selector_Mod GitHub Wiki

package playasmob;

import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Item;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.AreaEffectCloud;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.util.Mth;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.EntityTypeTags;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.chat.Component;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.Holder;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.entity.state.CreeperRenderState;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.CreeperRenderer;

import java.util.Optional;
import java.util.List;
import java.util.Collection;

public class CreeperInfo extends MonsterInfo {
	public static final Synched swellDir = Synched.SwellDir;
	public static final Synched swell = Synched.Swell;
	public static final Synched powered = Synched.Powered;
	public static final Synched ignited = Synched.Ignited;
	public int oldSwell;
	public int maxSwell = 30;
	public int explosionRadius = 3;
	public int droppedSkulls;

	public CreeperInfo(Player player, CompoundTag compound) {
		super(EntityType.CREEPER, Creeper.class, player, compound);
	}

	public CreeperInfo(Player player) {
		this(player, null);
	}

	public CreeperInfo() {
		this(null);
	}

	// Custom Code
	@Override
	public void delayedInit() {
		super.delayedInit();
		this.setSwellDir(-1);
	}
	
	@Override
	public void reset() {
		super.reset();
		this.reset(swellDir);
		this.reset(swell);
		this.reset(powered);
		this.reset(ignited);
		this.oldSwell = 0;
		this.maxSwell = 30;
		this.explosionRadius = 3;
		this.droppedSkulls = 0;
	}
	
	@Override
	public EntityRenderer getRenderer() {
		return new CreeperRenderer(Utils.getContext());
	}

	@Override
	public EntityRenderState createState() {
		return new CreeperRenderState();
	}

	@Override
	public void modifyState(EntityRenderState state) {
		super.modifyState(state);
		if (state instanceof CreeperRenderState creeperState) {
			creeperState.swelling = this.getSwelling(state.partialTick);
			creeperState.isPowered = this.isPowered();
		}
	}

	@Override
	public void press(int key, boolean pressed, int time) {
		if (key == 1)
			this.setSwellDir(this.canSwell() && pressed ? 1 : -1);
	}

	@Override
	public List<HudIcon> getIcons(float partialTick) {
		if(this.isSpectator())
			return super.getIcons(partialTick);
		float swellPercent = Math.min(this.getSwelling(partialTick) * 100, 100);
		int tntIndex = Math.round((swellPercent / 100) * 17);
		String tntTexture = "playasmob:textures/screens/tnt" + (tntIndex < 17 ? "_" + tntIndex : "") + ".png";
		HudIcon swellAbility = new HudIcon("playasmob:textures/screens/creeper" + (this.player.tickCount % 30 < 20 ? ".png" : "_flash.png")).key(Keybinds.Key1).useable(this.canSwell());
		HudIcon swellIndicator = new HudIcon(tntTexture).text(Component.literal((int) swellPercent + "%")).iconWidth(20).iconHeight(20);
		List<HudIcon> creeperIcons = this.canSwell() ? List.of(swellAbility, swellIndicator.offsetX(swellAbility, true)) : List.of(swellAbility);
		return Utils.merge(super.getIcons(partialTick), creeperIcons);
	}

	public boolean canSwell() {
		return !this.isSpectator() && this.isAlive() && (this.isIgnited() || (this.canUseHands(HandUse.Blocked) && !this.isSprinting()));
	}

	@Override
	public boolean canSprint(boolean original) {
		return super.canSprint(original) && this.<Integer>get(swell) == 0;
	}

	@Override
	public boolean handUseageBlocked() {
		return super.handUseageBlocked() || this.<Integer>get(swell) != 0;
	}

	@Override
	public void respawn() {
		super.respawn();
		this.set(shouldRender, true);
	}

	@Override
	public Diet getDiet() {
		Diet diet = new Diet();
		diet.allowNormalFood = true;
		diet.addFood(Items.GUNPOWDER, true, FoodFactory.createFoodData(1, 0.3f));
		return diet;
	}

	// Creeper.class Code
	@Override
	public int getMaxFallDistance(int original) {
		return this.getTarget() == null ? original : original + (int) (this.getHealth() - 1);
	}

	@Override
	public boolean causeFallDamage(boolean original, float distance, float multiplier, DamageSource source) {
		if (this.getMaxFallDistance() < distance) {
			this.set(swell, this.<Integer>get(swell) + (int) (distance * 1.5f));
			if (this.<Integer>get(swell) > this.maxSwell - 5)
				this.set(swell, this.maxSwell - 5);
		}
		return super.causeFallDamage(original, distance, multiplier, source);
	}

	@Override
	public CompoundTag saveData() {
		CompoundTag compound = super.saveData();
		if (this.get(powered))
			compound.putBoolean("powered", true);
		compound.putShort("Fuse", (short) this.maxSwell);
		compound.putByte("ExplosionRadius", (byte) this.explosionRadius);
		compound.putBoolean("ignited", this.isIgnited());
		return compound;
	}

	@Override
	public void loadData(CompoundTag compound) {
		super.loadData(compound);
		this.set(powered, compound.getBoolean("powered"));
		if (compound.contains("Fuse", 99))
			this.maxSwell = compound.getShort("Fuse");
		if (compound.contains("ExplosionRadius", 99))
			this.explosionRadius = compound.getByte("ExplosionRadius");
		if (compound.getBoolean("ignited"))
			this.ignite();
	}

	@Override
	public void preTick() {
		if (this.isAlive()) {
			this.oldSwell = this.<Integer>get(swell);
			if (this.isIgnited())
				this.setSwellDir(1);
			int i = this.getSwellDir();
			if (i == 1 && !this.canSwell())
				i = -1;
			if (i > 0 && this.<Integer>get(swell) == 0) {
				this.playSound(SoundEvents.CREEPER_PRIMED, 1, 0.5f);
				this.gameEvent(GameEvent.PRIME_FUSE);
			}
			this.set(swell, this.<Integer>get(swell) + i);
			if (this.<Integer>get(swell) < 0)
				this.set(swell, 0);
			if (this.<Integer>get(swell) >= this.maxSwell) {
				this.set(swell, this.maxSwell);
				this.explodeCreeper();
			}
		}
		super.preTick();
	}

	@Override
	public SoundEvent getHurtSound(SoundEvent original, DamageSource source) {
		return SoundEvents.CREEPER_HURT;
	}

	@Override
	public SoundEvent getDeathSound(SoundEvent original) {
		return SoundEvents.CREEPER_DEATH;
	}

	@Override
	public boolean dropCustomDeathLoot(Object object, ServerLevel server, DamageSource source, boolean booleanValue) {
		if (!super.dropCustomDeathLoot(null, server, source, booleanValue))
			return false;
		Entity entity = source.getEntity();
		if (entity != this.getEntity() && entity instanceof Creeper creeper && creeper.canDropMobsSkull()) {
			creeper.increaseDroppedSkulls();
			this.spawnAtLocation(server, Items.CREEPER_HEAD);
		} else if (entity != this.getEntity() && entity instanceof InfoHolder holder && holder.getInfo() instanceof CreeperInfo creeper && creeper.canDropMobsSkull()) {
			creeper.increaseDroppedSkulls();
			this.spawnAtLocation(server, Items.CREEPER_HEAD);
		}
		if (entity instanceof LivingEntity && entity.getType().is(EntityTypeTags.SKELETONS))
			this.spawnAtLocation(server, randomDisc());
		return true;
	}

	public ItemStack randomDisc() {
		Optional<Holder<Item>> disc = BuiltInRegistries.ITEM.getRandomElementOf(ItemTags.CREEPER_DROP_MUSIC_DISCS, this.random);
		return disc.isEmpty() ? ItemStack.EMPTY : new ItemStack(disc.get().value());
	}

	public boolean isPowered() {
		return this.get(powered);
	}

	public float getSwelling(float partialTick) {
		int currentSwell = this.get(swell);
		return Mth.lerp(partialTick, (float) this.oldSwell, (float) currentSwell) / (float) (this.maxSwell - 2);
	}

	public int getSwellDir() {
		return this.get(swellDir);
	}

	public void setSwellDir(int direction) {
		this.set(swellDir, direction);
	}

	@Override
	public boolean thunderHit(Object object, ServerLevel server, LightningBolt bolt) {
		if (!super.thunderHit(null, server, bolt))
			return false;
		this.set(powered, true);
		return true;
	}

	public void explodeCreeper() {
		if (this.level() instanceof ServerLevel server) {
			this.set(shouldRender, false);
			float f = this.isPowered() ? 2 : 1;
			server.explode(this.getEntity(), this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB);
			this.setHealth(0);
			if (this.getEntity() instanceof LivingEntity self)
				self.die(server.damageSources().explosion(self, self));
			this.set(swell, 0);
			this.setSwellDir(-1);
			this.spawnLingeringCloud();
		}
	}

	public void spawnLingeringCloud() {
		Collection<MobEffectInstance> effects = this.getActiveEffects();
		if (!effects.isEmpty()) {
			AreaEffectCloud cloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
			cloud.setRadius(2.5f);
			cloud.setRadiusOnUse(-0.5f);
			cloud.setWaitTime(10);
			cloud.setDuration(cloud.getDuration() / 2);
			cloud.setRadiusPerTick(-cloud.getRadius() / (float) cloud.getDuration());
			effects.forEach((effect) -> cloud.addEffect(new MobEffectInstance(effect)));
			this.level().addFreshEntity(cloud);
		}
	}

	public boolean isIgnited() {
		return this.get(ignited);
	}

	public void ignite() {
		this.set(ignited, true);
	}

	public boolean canDropMobsSkull() {
		return this.isPowered() && this.droppedSkulls < 1;
	}

	public void increaseDroppedSkulls() {
		this.droppedSkulls++;
	}
}
⚠️ **GitHub.com Fallback** ⚠️