package joshie.progression.helpers;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import joshie.progression.api.criteria.IFilter;
import joshie.progression.api.criteria.IFilterProvider;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.passive.EntityRabbit;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import java.util.concurrent.Callable;
public class EntityHelper {
private static final Cache<EntityLivingBase, Pair<Integer, Integer>> cacheScaleOffset = CacheBuilder.newBuilder().maximumSize(16).build();
private static final Cache<EntityLivingBase, ItemStack> eggCache = CacheBuilder.newBuilder().maximumSize(256).build();
private static final HashMap<String, Pair<Integer, Integer>> scaleOffset = new HashMap<String, Pair<Integer, Integer>>();
private static List<EntityLivingBase> clientList;
private static List<EntityLivingBase> serverList;
private static void register(String entity, int scale, int offset) {
scaleOffset.put(entity, Pair.of(scale, offset));
}
static {
register("Thaumcraft.TaintacleTiny", 15, -15);
register("Thaumcraft.Taintacle", 15, -45);
register("Giant", 3, 0);
register("WitherBoss", 10, 0);
register("Thaumcraft.EldritchGolem", 11, 0);
register("EnderDragon", 4, -4);
register("Ghast", 5, -30);
register("Thaumcraft.EldritchWarden", 4, 11);
}
public static int getSizeForEntity(final EntityLivingBase entity) {
try {
return cacheScaleOffset.get(entity, new Callable<Pair<Integer, Integer>>() {
@Override
public Pair<Integer, Integer> call() throws Exception {
String name = (EntityList.getEntityString(entity));
return scaleOffset.containsKey(name) ? scaleOffset.get(name) : Pair.of(15, 0);
}
}).getKey();
} catch (Exception e) { return 15; }
}
public static int getOffsetForEntity(final EntityLivingBase entity) {
try {
return cacheScaleOffset.get(entity, new Callable<Pair<Integer, Integer>>() {
@Override
public Pair<Integer, Integer> call() throws Exception {
String name = (EntityList.getEntityString(entity));
return scaleOffset.containsKey(name) ? scaleOffset.get(name) : Pair.of(15, 0);
}
}).getValue();
} catch (Exception e) { return 0; }
}
@SideOnly(Side.CLIENT)
public static List<EntityLivingBase> getEntities() {
if (clientList == null) clientList = init(MCClientHelper.getMinecraft().theWorld);
return clientList;
}
public static IFilter getFilter(List<IFilterProvider> filters, EntityPlayer player) {
if (player == null) return null;
int size = filters.size();
if (size == 0) return null;
if (size == 1) return filters.get(0).getProvided();
else {
return filters.get(player.worldObj.rand.nextInt(size)).getProvided();
}
}
public static EntityLivingBase getRandomEntityFromFilters(List<IFilterProvider> locality, EntityPlayer player) {
if (player == null) return null;
int size = locality.size();
if (size == 0) return null;
if (size == 1) {
List<EntityLivingBase> list = ((List<EntityLivingBase>) locality.get(0).getProvided().getRandom(player));
if (list.size() == 1) return list.get(0);
else if (list.size() > 1) return list.get(player.worldObj.rand.nextInt(list.size()));
else return null;
}
else {
List<EntityLivingBase> list = ((List<EntityLivingBase>) locality.get(player.worldObj.rand.nextInt(size)).getProvided().getRandom(player));
if (list.size() == 1) return list.get(0);
else if (list.size() > 1) return list.get(player.worldObj.rand.nextInt(list.size()));
else return null;
}
}
public static String getNameForEntity(EntityLivingBase living) {
return EntityList.getEntityString(living);
}
private static List<EntityLivingBase> init(World world) {
List<EntityLivingBase> list = new ArrayList<EntityLivingBase>();
for (String name : EntityList.NAME_TO_CLASS.keySet()) {
if (name.equals("Mob") || name.equals("Monster")) continue;
Entity entity = EntityList.createEntityByName(name, world);
if (entity instanceof EntityLivingBase) {
list.add((EntityLivingBase) entity);
//Special case addition of entities
//Wither Skeleton, Add to list
if (entity.getClass() == EntitySkeleton.class) {
entity = EntityList.createEntityByName(name, world);
((EntitySkeleton) entity).setSkeletonType(1);
list.add((EntityLivingBase) entity);
}
//Rabbit Variants
if (entity instanceof EntityRabbit) {
for (int i = 0; i < 6; i++) {
entity = EntityList.createEntityByName(name, world);
((EntityRabbit)entity).setRabbitType(i);
list.add((EntityLivingBase) entity);
}
}
}
}
return list;
}
public static EntityLivingBase getRandomEntity(World world, IFilterProvider filter) {
if (serverList == null) serverList = init(world);
Collections.shuffle(serverList);
for (EntityLivingBase entity : serverList) {
if (filter == null) return entity; //If we passed a null filter, return anything
if (filter.getProvided().matches(entity)) return entity;
}
//In theory if set up correctly this should be no issue
return null;
}
public static ItemStack getItemForEntity(final EntityLivingBase entity) {
try {
return eggCache.get(entity, new Callable<ItemStack>() {
@Override
public ItemStack call() throws Exception {
int id = EntityList.getEntityID(entity);
if (id != 0) {
return new ItemStack(Items.SPAWN_EGG, 1, id);
}
String name = EntityList.getEntityString(entity);
ItemStack stack = new ItemStack(Items.SPAWN_EGG);
net.minecraft.nbt.NBTTagCompound nbt = new net.minecraft.nbt.NBTTagCompound();
nbt.setString("entity_name", name);
stack.setTagCompound(nbt);
return stack;
}
});
} catch (Exception e) {}
return new ItemStack(Items.SPAWN_EGG);
}
private static WeakHashMap<EntityLivingBase, String> modentityidcache = new WeakHashMap();
public static String getModFromEntity(EntityLivingBase entity) {
if (modentityidcache.containsKey(entity)) return modentityidcache.get(entity);
else {
String name = (EntityList.getEntityString(entity));
String modid = "minecraft";
if (name.contains(".")) {
modid = name.substring(0, name.indexOf(".")).replace(".", "");
}
modentityidcache.put(entity, modid);
return modid;
}
}
public static EntityLivingBase clone(World world, EntityLivingBase entity, NBTTagCompound tagValue, IFilter filter) {
EntityLivingBase clone = (EntityLivingBase) EntityList.createEntityByName(EntityHelper.getNameForEntity(entity), world);
if (clone instanceof EntityLiving) {
((EntityLiving) clone).onInitialSpawn(world.getDifficultyForLocation(new BlockPos(clone)), null);
}
if (tagValue != null) {
clone.readEntityFromNBT(tagValue);
}
filter.apply(entity);
return clone;
}
}