Source BaseInfo - Spiderman31807/Mob_Selector_Mod GitHub Wiki

package playasmob;

import net.minecraft.world.level.gameevent.GameEventListener;
import net.minecraft.world.item.component.Consumable;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.ai.attributes.DefaultAttributes;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.InteractionHand;
import net.minecraft.util.RandomSource;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.network.chat.Component;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.Holder;

import java.util.List;
import java.util.ArrayList;

public abstract class BaseInfo implements InfoBundle {
	public final ArrayList<GameEventListener> listeners = new ArrayList();
	public final EntityType type;
	public final Class typeClass;
	public RandomSource random;
	public Player player;

	public BaseInfo(EntityType type, Class typeClass, Player player, CompoundTag compound) {
		this.type = type;
		this.typeClass = typeClass;
		this.setHolder(player);
		if (compound != null)
			this.loadData(compound);
	}

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

	public BaseInfo() {
		this(null);
	}

	public CompoundTag saveData() {
		CompoundTag compound = new CompoundTag();
		if(this instanceof MaturableInfo maturable)
			compound.putBoolean("IsBaby", maturable.isBaby());
		if(this instanceof SmelterInfo smelter)
			compound.put("SmeltData", smelter.saveSmelt());
		return compound;
	}

	public void loadData(CompoundTag compound) {
		if(this instanceof MaturableInfo maturable)
			maturable.setBaby(compound.getBoolean("IsBaby"));
		if(compound.contains("SmeltData") && this instanceof SmelterInfo smelter)
			smelter.loadSmelt(compound.getCompound("SmeltData"));
	}

	@Override
	public final boolean skipRender() {
		return !this.<Boolean>get(shouldRender);
	}

	public final void updateDimensions() {
		final Pose previousPose = this.getPose();
		this.setPose(previousPose == Pose.SLIDING ? Pose.USING_TONGUE : Pose.SLIDING);
		Utils.delay(1, () -> {
			this.setPose(previousPose);
		});
	}

	public final void setHolder(Player player) {
		this.player = player;
		this.random = player == null ? null : player.getRandom();
	}

	public final int getIndex() {
		return this.getInfoType().getIndex();
	}

	public final ArrayList<GameEventListener> getListeners() {
		return this.listeners;
	}

	public final Entity getEntity() {
		return this.player;
	}

	public final void changeInfo(EntityType type, boolean convertData) {
		this.changeInfo(type, convertData ? this.saveData() : null);
	}

	public final void changeInfo(InfoType type, boolean convertData) {
		this.changeInfo(type, convertData ? this.saveData() : null);
	}

	public final void changeInfo(EntityType type, CompoundTag loadData) {
		this.changeInfo(InfoType.byEntity(type, null), loadData);
	}

	public final void changeInfo(InfoType type, CompoundTag loadData) {
		if (type != null && this.getPlayer() instanceof InfoHolder holder) {
			logger.debug("Changing Info from " + this.getClass().getSimpleName() + " to " + type.info.getClass().getSimpleName());
			holder.setInfo(type, loadData, Activatable.Type.Change);
		}
	}

	@Override
	public EntityType getType(EntityType original) {
		return type;
	}

	public final Class getTypeClass() {
		return this.typeClass;
	}

	public final InfoType getInfoType() {
		return InfoType.byEntity(this.getType(EntityType.PLAYER), InfoType.Player);
	}

	public LivingEntity getTarget() {
		return null;
	}

	public void ate(ItemStack stack, Consumable consumer, FoodProperties foodInfo) {
	}

	public boolean handUseageBlocked() {
		return false;
	}

	public HandUse getHandUseage(boolean includeBlocked) {
		if (this.isDeadOrDying())
			return HandUse.Missing;
		if (includeBlocked && this.handUseageBlocked())
			return HandUse.Blocked;
		if (this.isUsingItem())
			return HandUse.UsingItem;
		return HandUse.None;
	}

	public boolean canUseHands(HandUse type) {
		HandUse currentUseage = this.getHandUseage(true);
		return currentUseage == HandUse.None || currentUseage == type;
	}

	public boolean canUseItem(ItemStack stack) {
		return this.canUseHands(HandUse.UsingItem);
	}

	@Override
	public double blockInteractionRange(double original) {
		return this.modifyInteractionRange(original);
	}

	@Override
	public double entityInteractionRange(double original) {
		return this.modifyInteractionRange(original);
	}

	public double modifyInteractionRange(double range) {
		if(!this.canUseHands(HandUse.None))
			return 0;
		
		EntityDimensions modifedHitbox = this.type.getDimensions();
		EntityDimensions defaultHitbox = EntityType.PLAYER.getDimensions();
		float widthDiff = modifedHitbox.width() - defaultHitbox.width();
		range += widthDiff;
		return range;
	}

	public boolean canTradeWith(Entity entity) {
		return false;
	}

	public void press(int key, boolean pressed, int time) {
		logger.debug("BaseInfo.press(); key: " + key + ", pressed: " + pressed + ", time: " + time + ", isClientSide: " + this.level().isClientSide);
	}

	@Override
	public void init() {
		this.updateDimensions();
		Utils.delay(1, () -> {
			this.setupAttributes();
		});
	}

	public void setupAttributes() {
		logger.debug("setupAttributes::start");
		if (!this.isBound())
			return;
		AttributeSupplier supplier = DefaultAttributes.getSupplier(this.type);
		for (Holder<Attribute> attribute : BuiltInRegistries.ATTRIBUTE.asHolderIdMap()) {
			if (!supplier.hasAttribute(attribute))
				continue;
			double base = supplier.getBaseValue(attribute);
			AttributeInstance instance = this.getLivingEntity().getAttribute(attribute);
			instance.setBaseValue(base);
		}
		logger.debug("setupAttributes::end");
	}

	public void replaceItemInSlot(ItemStack stack, EquipmentSlot slot, boolean drop) {
		if (!this.isBound() || this.level().isClientSide || stack == null || stack.isEmpty() || stack.getCount() == 0)
			return;
		ItemStack precursor = this.getItemBySlot(slot).copy();
		if (precursor == null || precursor.isEmpty() || precursor.getCount() == 0) {
			this.setItemSlot(slot, stack);
		} else if (ItemStack.isSameItemSameComponents(precursor, stack) && precursor.getCount() < precursor.getMaxStackSize()) {
			int total = precursor.getCount() + stack.getCount();
			int remaining = total - stack.getMaxStackSize();
			stack.setCount(Math.min(total, stack.getMaxStackSize()));
			this.setItemSlot(slot, stack);
			if (remaining > 0) {
				precursor.setCount(remaining);
				boolean added = false;
				if (!drop)
					added = this.addItem(precursor);
				if (!added)
					this.drop(precursor, true);
			}
		} else {
			this.setItemSlot(slot, stack);
			boolean added = false;
			if (!drop)
				added = this.addItem(precursor);
			if (!added)
				this.drop(precursor, true);
		}
	}

	public EntityDimensions getDimensions(Pose pose) {
		return this.dynamicHitbox(this.getType().getDimensions(), pose);
	}

	public EntityDimensions dynamicHitbox(EntityDimensions hitbox, Pose pose) {
		float smallerSide = Math.min(hitbox.width(), hitbox.height());
		EntityDimensions smallHitbox = EntityDimensions.scalable(smallerSide, smallerSide);
		EntityDimensions tinyHitbox = EntityDimensions.scalable(smallerSide * 0.666f, smallerSide * 0.666f);
		hitbox = switch (pose) {
			default -> hitbox;
			case FALL_FLYING -> smallHitbox;
			case SLEEPING -> tinyHitbox;
			case SWIMMING -> smallHitbox;
			case SPIN_ATTACK -> smallHitbox;
			case CROUCHING -> EntityDimensions.scalable(hitbox.width(), hitbox.height() * 0.833f);
			case DYING -> tinyHitbox;
		};
		if (!this.isBound())
			return hitbox;
		return hitbox.scale(this.getAgeScale());
	}

	public void preTick() {
	}

	public void postTick() {
		if(this instanceof SmelterInfo smelter)
			smelter.tick();
	}

	public void shotProjectile(ServerLevel server, InteractionHand hand, ItemStack weapon, List<ItemStack> projectiles, boolean isCrit, LivingEntity target) {
	}

	public ItemStack getDefaultProjectile(ItemStack weapon) {
		return null;
	}

	@Override
	public ItemStack getProjectile(ItemStack original, ItemStack weapon) {
		if (!this.isBound())
			return original;
		ItemStack defaultProjectile = this.getDefaultProjectile(weapon);
		if (defaultProjectile != null) {
			defaultProjectile.set(DataComponents.ITEM_NAME, Component.literal("defaulted_projectile"));
			if (original == null || original.isEmpty())
				return defaultProjectile;
		}
		return original;
	}

	public void modifyArrow(AbstractArrow arrow, ItemStack projectileStack, ItemStack weaponStack) {
		if (!this.isBound())
			return;
		if (projectileStack.get(DataComponents.ITEM_NAME).getString().equals("defaulted_projectile"))
			arrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
	}

	@Override
	public float getSpeed(float original) {
		return original * (this.isSprinting() ? 0.33f : 0.25f);
	}
}
⚠️ **GitHub.com Fallback** ⚠️