package com.matt.forgehax.util.entity; import static com.matt.forgehax.Helper.getLocalPlayer; import static com.matt.forgehax.Helper.getRidingEntity; import static com.matt.forgehax.Helper.getWorld; import com.matt.forgehax.Globals; import com.matt.forgehax.asm.reflection.FastReflection; import com.matt.forgehax.util.color.Colors; import com.matt.forgehax.util.entity.mobtypes.MobType; import com.matt.forgehax.util.entity.mobtypes.MobTypeEnum; import com.matt.forgehax.util.entity.mobtypes.MobTypeRegistry; import java.util.List; import java.util.Objects; import net.minecraft.block.BlockLiquid; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.monster.EntityEnderman; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.monster.EntityPigZombie; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.passive.EntityWolf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class EntityUtils implements Globals { public static MobTypeEnum getRelationship(Entity entity) { if (entity instanceof AbstractClientPlayer) { return MobTypeEnum.PLAYER; } else { // check special cases first for (MobType type : MobTypeRegistry.getSortedSpecialMobTypes()) { if (type.isMobType(entity)) { return type.getMobType(entity); } } // this code will continue if no special was found if (MobTypeRegistry.HOSTILE.isMobType(entity)) { return MobTypeEnum.HOSTILE; } else if (MobTypeRegistry.FRIENDLY.isMobType(entity)) { return MobTypeEnum.FRIENDLY; } else { return MobTypeEnum.HOSTILE; // default to hostile } } } public static boolean isBatsDisabled = false; /** * Checks if the mob could be possibly hostile towards us (we can't detect their attack target * easily) Current entities: PigZombie: Aggressive if arms are raised, when arms are put down a * internal timer is slowly ticked down from 400 Wolf: Aggressive if the owner isn't the local * player and the wolf is angry Enderman: Aggressive if making screaming sounds */ public static boolean isMobAggressive(Entity entity) { if (entity instanceof EntityPigZombie) { // arms raised = aggressive, angry = either game or we have set the anger cooldown if (((EntityPigZombie) entity).isArmsRaised() || ((EntityPigZombie) entity).isAngry()) { if (!((EntityPigZombie) entity).isAngry()) { // set pigmens anger to 400 if it hasn't been angered already FastReflection.Fields.EntityPigZombie_angerLevel.set(entity, 400); } return true; } } else if (entity instanceof EntityWolf) { return ((EntityWolf) entity).isAngry() && !MC.player.equals(((EntityWolf) entity).getOwner()); } else if (entity instanceof EntityEnderman) { return ((EntityEnderman) entity).isScreaming(); } return false; } /** * Check if the mob is an instance of EntityLivingBase */ public static boolean isLiving(Entity entity) { return entity instanceof EntityLivingBase; } /** * If the entity is a player */ public static boolean isPlayer(Entity entity) { return entity instanceof EntityPlayer; } public static boolean isLocalPlayer(Entity entity) { return Objects.equals(getLocalPlayer(), entity); } public static boolean isFakeLocalPlayer(Entity entity) { return entity != null && entity.getEntityId() == -100; } public static boolean isValidEntity(Entity entity) { Entity riding = getLocalPlayer().getRidingEntity(); return entity.ticksExisted > 1 && !isFakeLocalPlayer(entity) && (riding == null || !riding.equals(entity)); } public static boolean isAlive(Entity entity) { return isLiving(entity) && !entity.isDead && ((EntityLivingBase) (entity)).getHealth() > 0; } /** * If the mob by default wont attack the player, but will if the player attacks it */ public static boolean isNeutralMob(Entity entity) { return entity instanceof EntityPigZombie || entity instanceof EntityWolf || entity instanceof EntityEnderman; } /** * If the mob is friendly (not aggressive) */ public static boolean isFriendlyMob(Entity entity) { return (entity.isCreatureType(EnumCreatureType.CREATURE, false) && !EntityUtils.isNeutralMob(entity)) || (entity.isCreatureType(EnumCreatureType.AMBIENT, false) && !isBatsDisabled) || entity instanceof EntityVillager || entity instanceof EntityIronGolem || (isNeutralMob(entity) && !EntityUtils.isMobAggressive(entity)); } /** * If the mob is hostile */ public static boolean isHostileMob(Entity entity) { return (entity.isCreatureType(EnumCreatureType.MONSTER, false) && !EntityUtils.isNeutralMob(entity)) || EntityUtils.isMobAggressive(entity); } /** * Find the entities interpolated amount */ public static Vec3d getInterpolatedAmount(Entity entity, double x, double y, double z) { return new Vec3d( (entity.posX - entity.lastTickPosX) * x, (entity.posY - entity.lastTickPosY) * y, (entity.posZ - entity.lastTickPosZ) * z); } public static Vec3d getInterpolatedAmount(Entity entity, Vec3d vec) { return getInterpolatedAmount(entity, vec.x, vec.y, vec.z); } public static Vec3d getInterpolatedAmount(Entity entity, double ticks) { return getInterpolatedAmount(entity, ticks, ticks, ticks); } /** * Find the entities interpolated position */ public static Vec3d getInterpolatedPos(Entity entity, double ticks) { return new Vec3d(entity.lastTickPosX, entity.lastTickPosY, entity.lastTickPosZ) .add(getInterpolatedAmount(entity, ticks)); } /** * Find the entities interpolated eye position */ public static Vec3d getInterpolatedEyePos(Entity entity, double ticks) { return getInterpolatedPos(entity, ticks).addVector(0, entity.getEyeHeight(), 0); } /** * Get entities eye position */ public static Vec3d getEyePos(Entity entity) { return new Vec3d(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ); } /** * Find the center of the entities hit box */ public static Vec3d getOBBCenter(Entity entity) { AxisAlignedBB obb = entity.getEntityBoundingBox(); return new Vec3d( (obb.maxX + obb.minX) / 2.D, (obb.maxY + obb.minY) / 2.D, (obb.maxZ + obb.minZ) / 2.D); } /** * Create a trace */ public static RayTraceResult traceEntity( World world, Vec3d start, Vec3d end, List<Entity> filter) { RayTraceResult result = null; double hitDistance = -1; for (Entity ent : world.loadedEntityList) { if (filter.contains(ent)) { continue; } double distance = start.distanceTo(ent.getPositionVector()); RayTraceResult trace = ent.getEntityBoundingBox().calculateIntercept(start, end); if (trace != null && (hitDistance == -1 || distance < hitDistance)) { hitDistance = distance; result = trace; result.entityHit = ent; } } return result; } /** * Find the entities draw color */ public static int getDrawColor(EntityLivingBase living) { if (isPlayer(living)) { if (PlayerUtils.isFriend((EntityPlayer) living)) { return Colors.GREEN.toBuffer(); } else { return Colors.RED.toBuffer(); } } else if (isHostileMob(living)) { return Colors.ORANGE.toBuffer(); } else if (isFriendlyMob(living)) { return Colors.GREEN.toBuffer(); } else { return Colors.WHITE.toBuffer(); } } public static boolean isDrivenByPlayer(Entity entityIn) { return getLocalPlayer() != null && entityIn != null && entityIn == getRidingEntity(); } public static boolean isAboveWater(Entity entity) { return isAboveWater(entity, false); } public static boolean isAboveWater(Entity entity, boolean packet) { if (entity == null) { return false; } double y = entity.posY - (packet ? 0.03 : (EntityUtils.isPlayer(entity) ? 0.2 : 0.5)); // increasing this seems to flag more in NCP but needs to be increased // so the player lands on solid water for (int x = MathHelper.floor(entity.posX); x < MathHelper.ceil(entity.posX); x++) { for (int z = MathHelper.floor(entity.posZ); z < MathHelper.ceil(entity.posZ); z++) { BlockPos pos = new BlockPos(x, MathHelper.floor(y), z); if (getWorld().getBlockState(pos).getBlock() instanceof BlockLiquid) { return true; } } } return false; } public static boolean isInWater(Entity entity) { if (entity == null) { return false; } double y = entity.posY + 0.01; for (int x = MathHelper.floor(entity.posX); x < MathHelper.ceil(entity.posX); x++) { for (int z = MathHelper.floor(entity.posZ); z < MathHelper.ceil(entity.posZ); z++) { BlockPos pos = new BlockPos(x, (int) y, z); if (getWorld().getBlockState(pos).getBlock() instanceof BlockLiquid) { return true; } } } return false; } }