package com.bergerkiller.bukkit.common.entity.nms; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.bergerkiller.bukkit.common.entity.CommonEntity; import com.bergerkiller.bukkit.common.internal.CommonNMS; import com.bergerkiller.bukkit.common.reflection.ClassBuilder; import com.bergerkiller.bukkit.common.reflection.classes.WorldRef; /** * Takes care of NMS Entity class creation, allowing multiple callback methods to be implemented. * All methods provided by a callback Class that are supposed to be inherited by the produced Entity * class instance, should be in a separate interface Class implemented by the callback class.<br> * <br> * For example, an 'InventoryHookImpl' class implementing 'InventoryHook', with InventoryHook * declaring the methods 'setItem' and 'super_setItem'.<br> * <br> * To call super methods, add methods in the interface starting with <i>super_</i>. * These methods are automatically redirected to the base Entity class.<br> * <br> * All callback classes must have a constructor that accepts a single CommonEntity instance. */ public class NMSEntityClassBuilder extends ClassBuilder { private static final Class<?>[] DEFAULT_CONSTRUCTOR_TYPES = {WorldRef.TEMPLATE.getType()}; private static final Object[] DEFAULT_CONSTRUCTOR_ARGS = {CommonNMS.getWorlds().iterator().next()}; private final List<Constructor<?>> callbackConstructors = new ArrayList<Constructor<?>>(); public NMSEntityClassBuilder(Class<?> superClass, Collection<Class<?>> callbackClasses) { super(superClass, callbackClasses); for (Class<?> callbackClass : this.getCallbackClasses()) { try { callbackConstructors.add(callbackClass.getConstructor(CommonEntity.class)); } catch (Throwable t) { throw new RuntimeException("Callback class '" + callbackClass.getName() + "' is invalid: No one-argument 'CommonEntity' constructor"); } } } /** * Creates a new Entity instance * * @return new Entiy instance */ public synchronized Object create(CommonEntity<?> entity, Object... args) { // Prepare new Callback instances List<Object> instances = new ArrayList<Object>(callbackConstructors.size()); for (Constructor<?> callbackConstructor : callbackConstructors) { try { instances.add(callbackConstructor.newInstance(entity)); } catch (Throwable t) { throw new RuntimeException("Unable to construct Callback Class:", t); } } // Create and return return create(DEFAULT_CONSTRUCTOR_TYPES, DEFAULT_CONSTRUCTOR_ARGS, instances); } }