001 package net.minecraftforge.event;
002
003 import java.lang.reflect.Constructor;
004 import java.lang.reflect.Method;
005 import java.util.ArrayList;
006 import java.util.Set;
007 import java.util.concurrent.ConcurrentHashMap;
008
009
010
011 import com.google.common.reflect.TypeToken;
012
013 public class EventBus
014 {
015 private static int maxID = 0;
016
017 private ConcurrentHashMap<Object, ArrayList<IEventListener>> listeners = new ConcurrentHashMap<Object, ArrayList<IEventListener>>();
018 private final int busID = maxID++;
019
020 public EventBus()
021 {
022 ListenerList.resize(busID + 1);
023 }
024
025 public void register(Object target)
026 {
027 Set<? extends Class<?>> supers = TypeToken.of(target.getClass()).getTypes().rawTypes();
028 for (Method method : target.getClass().getMethods())
029 {
030 for (Class<?> cls : supers)
031 {
032 try
033 {
034 Method real = cls.getDeclaredMethod(method.getName(), method.getParameterTypes());
035 if (real.isAnnotationPresent(ForgeSubscribe.class))
036 {
037 Class<?>[] parameterTypes = method.getParameterTypes();
038 if (parameterTypes.length != 1)
039 {
040 throw new IllegalArgumentException(
041 "Method " + method + " has @ForgeSubscribe annotation, but requires " + parameterTypes.length +
042 " arguments. Event handler methods must require a single argument."
043 );
044 }
045
046 Class<?> eventType = parameterTypes[0];
047
048 if (!Event.class.isAssignableFrom(eventType))
049 {
050 throw new IllegalArgumentException("Method " + method + " has @ForgeSubscribe annotation, but takes a argument that is not a Event " + eventType);
051 }
052
053 register(eventType, target, method);
054 break;
055 }
056 }
057 catch (NoSuchMethodException e)
058 {
059 ;
060 }
061 }
062 }
063 }
064
065 private void register(Class<?> eventType, Object target, Method method)
066 {
067 try
068 {
069 Constructor<?> ctr = eventType.getConstructor();
070 ctr.setAccessible(true);
071 Event event = (Event)ctr.newInstance();
072 ASMEventHandler listener = new ASMEventHandler(target, method);
073 event.getListenerList().register(busID, listener.getPriority(), listener);
074
075 ArrayList<IEventListener> others = listeners.get(target);
076 if (others == null)
077 {
078 others = new ArrayList<IEventListener>();
079 listeners.put(target, others);
080 }
081 others.add(listener);
082 }
083 catch (Exception e)
084 {
085 e.printStackTrace();
086 }
087 }
088
089 public void unregister(Object object)
090 {
091 ArrayList<IEventListener> list = listeners.remove(object);
092 for (IEventListener listener : list)
093 {
094 ListenerList.unregiterAll(busID, listener);
095 }
096 }
097
098 public boolean post(Event event)
099 {
100 IEventListener[] listeners = event.getListenerList().getListeners(busID);
101 for (IEventListener listener : listeners)
102 {
103 listener.invoke(event);
104 }
105 return (event.isCancelable() ? event.isCanceled() : false);
106 }
107 }