package net.citizensnpcs.npc; import java.lang.reflect.Constructor; import java.util.Map; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.util.NMS; import net.minecraft.server.Block; import net.minecraft.server.EntityLiving; import net.minecraft.server.World; import org.bukkit.Location; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.CraftWorld; import com.google.common.collect.Maps; public abstract class CitizensMobNPC extends CitizensNPC { private final Constructor constructor; protected CitizensMobNPC(int id, String name, Class clazz) { super(id, name); this.constructor = getConstructor(clazz); NMS.registerEntityClass(clazz); } private EntityLiving createEntityFromClass(World world) { try { return constructor.newInstance(world, this); } catch (Exception ex) { ex.printStackTrace(); return null; } } @Override protected EntityLiving createHandle(Location loc) { EntityLiving entity = createEntityFromClass(((CraftWorld) loc.getWorld()).getHandle()); entity.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); // entity.onGround isn't updated right away - we approximate here so // that things like pathfinding still work *immediately* after spawn. org.bukkit.Material beneath = loc.getBlock().getRelative(BlockFace.DOWN).getType(); if (beneath.isBlock()) { Block block = Block.byId[beneath.getId()]; if (block != null && block.material != null) { entity.onGround = block.material.isSolid(); } } return entity; } private static final Map, Constructor> CONSTRUCTOR_CACHE = Maps .newHashMap(); private static Constructor getConstructor(Class clazz) { Constructor constructor = CONSTRUCTOR_CACHE.get(clazz); if (constructor != null) return constructor; try { return clazz.getConstructor(World.class, NPC.class); } catch (Exception ex) { throw new IllegalStateException("unable to find an entity constructor"); } } }