001package net.minecraftforge.event;
002
003import static java.lang.annotation.ElementType.TYPE;
004import static java.lang.annotation.RetentionPolicy.RUNTIME;
005
006import java.lang.annotation.Retention;
007import java.lang.annotation.Target;
008
009
010/**
011 * Base Event class that all other events are derived from
012 */
013public class Event
014{
015    @Retention(value = RUNTIME)
016    @Target(value = TYPE)
017    public @interface HasResult{}
018
019    public enum Result
020    {
021        DENY,
022        DEFAULT,
023        ALLOW
024    }
025
026    private boolean isCanceled = false;
027    private final boolean isCancelable;
028    private Result result = Result.DEFAULT;
029    private final boolean hasResult;
030    private static ListenerList listeners = new ListenerList();
031    
032    public Event()
033    {
034        setup();
035        isCancelable = hasAnnotation(Cancelable.class);
036        hasResult = hasAnnotation(HasResult.class);
037    }
038
039    private boolean hasAnnotation(Class annotation)
040    {
041        Class cls = this.getClass();
042        while (cls != Event.class)
043        {
044            if (cls.isAnnotationPresent(Cancelable.class))
045            {
046                return true;
047            }
048            cls = cls.getSuperclass();
049        }
050        return false;
051    }
052
053    /**
054     * Determine if this function is cancelable at all. 
055     * @return If access to setCanceled should be allowed
056     */
057    public boolean isCancelable()
058    {
059        return isCancelable;
060    }
061
062    /**
063     * Determine if this event is canceled and should stop executing.
064     * @return The current canceled state
065     */
066    public boolean isCanceled()
067    {
068        return isCanceled;
069    }
070
071    /**
072     * Sets the state of this event, not all events are cancelable, and any attempt to
073     * cancel a event that can't be will result in a IllegalArgumentException.
074     * 
075     * The functionality of setting the canceled state is defined on a per-event bases.
076     * 
077     * @param cancel The new canceled value
078     */
079    public void setCanceled(boolean cancel)
080    {
081        if (!isCancelable())
082        {
083            throw new IllegalArgumentException("Attempted to cancel a uncancelable event");
084        }
085        isCanceled = cancel;
086    }
087
088    /**
089     * Determines if this event expects a significant result value.
090     */
091    public boolean hasResult()
092    {
093        return hasResult;
094    }
095
096    /**
097     * Returns the value set as the result of this event
098     */
099    public Result getResult()
100    {
101        return result;
102    }
103
104    /**
105     * Sets the result value for this event, not all events can have a result set, and any attempt to
106     * set a result for a event that isn't expecting it will result in a IllegalArgumentException.
107     * 
108     * The functionality of setting the result is defined on a per-event bases.
109     * 
110     * @param value The new result
111     */
112    public void setResult(Result value)
113    {
114        result = value;
115    }
116    /**
117     * Called by the base constructor, this is used by ASM generated 
118     * event classes to setup various functionality such as the listener's list.
119     */
120    protected void setup()
121    {
122    }
123    
124    /**
125     * Returns a ListenerList object that contains all listeners
126     * that are registered to this event.
127     * 
128     * @return Listener List
129     */
130    public ListenerList getListenerList()
131    {
132        return listeners;
133    }
134}