    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    }