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