package com.forgeessentials.commands.util; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import net.minecraft.command.ICommandSender; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.boss.EntityDragon; import net.minecraft.entity.boss.EntityDragonPart; import net.minecraft.entity.boss.EntityWither; import net.minecraft.entity.monster.EntityGhast; import net.minecraft.entity.monster.EntityGolem; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.EntitySlime; import net.minecraft.entity.passive.EntityAmbientCreature; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntitySquid; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import org.apache.commons.lang3.StringUtils; import com.forgeessentials.api.EnumMobType; import com.forgeessentials.core.misc.TaskRegistry; import com.forgeessentials.core.misc.TaskRegistry.TickTask; import com.forgeessentials.core.misc.TranslatedCommandException; import com.forgeessentials.core.misc.Translator; import com.forgeessentials.util.output.ChatOutputHandler; public class CommandButcherTickTask implements TickTask { public static enum ButcherMobType { ALL, HOSTILE, PASSIVE, VILLAGER, TAMABLE, TAMED, GOLEM, BOSS; public static List<String> getNames() { List<String> result = new ArrayList<>(); for (ButcherMobType type : ButcherMobType.values()) result.add(type.name()); return result; } } private ICommandSender sender; private ButcherMobType mobType; private AxisAlignedBB aabb; private World world; private int radius; private int maxChunkX; private int maxChunkZ; private int minChunkX; private int minChunkZ; private int killCount; private int tickKillCount; private static final int MAX_TICK_KILLS = 1; public CommandButcherTickTask(ICommandSender sender, World world, ButcherMobType mobType, AxisAlignedBB aabb, int radius) { this.sender = sender; this.mobType = mobType; this.radius = radius; this.world = world; if (radius > -1) { this.aabb = aabb; minChunkX = MathHelper.floor_double((aabb.minX - World.MAX_ENTITY_RADIUS) / 16.0D); maxChunkX = MathHelper.floor_double((aabb.maxX + World.MAX_ENTITY_RADIUS) / 16.0D); minChunkZ = MathHelper.floor_double((aabb.minZ - World.MAX_ENTITY_RADIUS) / 16.0D); maxChunkZ = MathHelper.floor_double((aabb.maxZ + World.MAX_ENTITY_RADIUS) / 16.0D); } } public CommandButcherTickTask(ICommandSender sender, World world, String mobType, AxisAlignedBB aabb, int radius) { this(sender, world, CommandButcherTickTask.ButcherMobType.valueOf(mobType.toUpperCase()), aabb, radius); } public static void schedule(ICommandSender sender, World world, String mobType, AxisAlignedBB aabb, int radius) { try { ButcherMobType mobT = CommandButcherTickTask.ButcherMobType.valueOf(mobType.toUpperCase()); TaskRegistry.getInstance().schedule(new CommandButcherTickTask(sender, world, mobT, aabb, radius)); } catch (IllegalArgumentException e) { throw new TranslatedCommandException("Unknown mob type. Mob types are " + StringUtils.join(CommandButcherTickTask.ButcherMobType.values(), ", ")); } } @Override public boolean tick() { tickKillCount = 0; if (radius < -1) return true; else if (radius == -1) { for (Object entity : world.loadedEntityList) if (entity instanceof EntityLiving) { checkEntity((EntityLiving) entity); if (tickKillCount >= 32) return false; } ChatOutputHandler.chatConfirmation(sender, Translator.format("%s mobs killed.", killCount)); } else { for (int chunkX = minChunkX; chunkX <= maxChunkX; ++chunkX) for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; ++chunkZ) if (world.getChunkProvider().chunkExists(chunkX, chunkZ)) { List<EntityLiving> list = new LinkedList<EntityLiving>(); world.getChunkFromChunkCoords(chunkX, chunkZ).getEntitiesOfTypeWithinAAAB(EntityLiving.class, aabb, list, null); for (EntityLiving entity : list) { checkEntity(entity); if (tickKillCount >= MAX_TICK_KILLS) return false; } } ChatOutputHandler.chatConfirmation(sender, Translator.format("%s mobs killed.", killCount)); } return true; } private void checkEntity(EntityLiving entity) { if (shouldKill(entity)) { killEntity(entity); killCount++; tickKillCount++; } } private boolean shouldKill(EntityLiving entity) { String className = entity.getClass().getName(); switch (mobType) { case ALL: return true; case HOSTILE: if (entity instanceof EntityMob || entity instanceof EntityGhast) return true; if (entity instanceof EntitySlime && ((EntitySlime) entity).getSlimeSize() > 0) return true; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.HOSTILE).contains(className)) return true; return false; case PASSIVE: // Filter out tamed creatures if (entity instanceof EntityTameable && ((EntityTameable) entity).isTamed()) return false; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.TAMEABLE).contains(className) && MobTypeRegistry.isTamed(entity)) return false; // Check for other creatures if (entity instanceof EntityAnimal || entity instanceof EntityAmbientCreature || entity instanceof EntitySquid) return true; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.PASSIVE).contains(className)) return true; return false; case VILLAGER: if (entity instanceof EntityVillager) return true; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.VILLAGER).contains(className)) return true; return false; case TAMABLE: if (entity instanceof EntityTameable) return true; return false; case TAMED: if (entity instanceof EntityTameable && ((EntityTameable) entity).isTamed()) return true; return false; case GOLEM: if (entity instanceof EntityGolem) return true; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.GOLEM).contains(className)) return true; return false; case BOSS: if (entity instanceof EntityDragon || entity instanceof EntityWither) return true; if (MobTypeRegistry.getCollectionForMobType(EnumMobType.BOSS).contains(className)) return true; default: return false; } } private static void killEntity(Entity entity) { if (entity instanceof EntityDragon) { for (EntityDragonPart part : ((EntityDragon) entity).dragonPartArray) part.setDead(); } entity.setDead(); } @Override public boolean editsBlocks() { return false; } }