diff --git a/src/main/java/dev/zontreck/eventsbus/Bus.java b/src/main/java/dev/zontreck/eventsbus/Bus.java
index fcf8cbd..a57ee68 100644
--- a/src/main/java/dev/zontreck/eventsbus/Bus.java
+++ b/src/main/java/dev/zontreck/eventsbus/Bus.java
@@ -1,14 +1,22 @@
package dev.zontreck.eventsbus;
+import dev.zontreck.eventsbus.annotations.Priority;
+import dev.zontreck.eventsbus.annotations.SingleshotEvent;
+import dev.zontreck.eventsbus.annotations.Subscribe;
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
+/**
+ * To be removed
+ *
+ * Use {} instead
+ */
+@Deprecated()
public class Bus {
/**
* The main event bus!
diff --git a/src/main/java/dev/zontreck/eventsbus/ClassScanner.java b/src/main/java/dev/zontreck/eventsbus/ClassScanner.java
new file mode 100644
index 0000000..03c88e9
--- /dev/null
+++ b/src/main/java/dev/zontreck/eventsbus/ClassScanner.java
@@ -0,0 +1,93 @@
+package dev.zontreck.eventsbus;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Used internally. Do not directly invoke
+ *
+ * Accessor is set Protected intentionally!!!!!!!!!
+ */
+class ClassScanner {
+ /**
+ * Start the process of scanning the classes and forcing them to load in
+ *
+ * This is used by the event dispatcher
+ */
+ protected static void DoScan() {
+ // Scan all classes in the classpath
+ Set> scannedClasses = scanClasses();
+
+ // Force loading of all scanned classes
+ for (Class> clazz : scannedClasses) {
+ try {
+ // Load the class
+ Class.forName(clazz.getName());
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static Set> scanClasses() {
+ String classpath = System.getProperty("java.class.path");
+ String[] classpathEntries = classpath.split(File.pathSeparator);
+
+ Set> scannedClasses = new HashSet<>();
+ for (String classpathEntry : classpathEntries) {
+ File file = new File(classpathEntry);
+ if (file.isDirectory()) {
+ scanClassesInDirectory(file, "", scannedClasses);
+ } else if (file.isFile() && classpathEntry.endsWith(".jar")) {
+ scanClassesInJar(file, scannedClasses);
+ }
+ }
+
+ return scannedClasses;
+ }
+
+ private static void scanClassesInDirectory(File directory, String packageName, Set> scannedClasses) {
+ File[] files = directory.listFiles();
+ if (files == null) {
+ return;
+ }
+
+ for (File file : files) {
+ if (file.isDirectory()) {
+ scanClassesInDirectory(file, packageName + "." + file.getName(), scannedClasses);
+ } else if (file.getName().endsWith(".class")) {
+ String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
+ try {
+ Class> clazz = Class.forName(className);
+ scannedClasses.add(clazz);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static void scanClassesInJar(File jarFile, Set> scannedClasses) {
+ try (JarFile jf = new JarFile(jarFile)) {
+ for (JarEntry entry : Collections.list(jf.entries())) {
+ if (entry.getName().endsWith(".class")) {
+ String className = entry.getName().replace("/", ".").substring(0, entry.getName().length() - 6);
+ try {
+ Class> clazz = Class.forName(className);
+ scannedClasses.add(clazz);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/dev/zontreck/eventsbus/Event.java b/src/main/java/dev/zontreck/eventsbus/Event.java
index 3c520de..1053644 100644
--- a/src/main/java/dev/zontreck/eventsbus/Event.java
+++ b/src/main/java/dev/zontreck/eventsbus/Event.java
@@ -1,6 +1,9 @@
package dev.zontreck.eventsbus;
+import dev.zontreck.eventsbus.annotations.Cancellable;
+import dev.zontreck.eventsbus.annotations.Priority;
+
public class Event {
private boolean cancelled = false;
diff --git a/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java b/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java
new file mode 100644
index 0000000..8cc210f
--- /dev/null
+++ b/src/main/java/dev/zontreck/eventsbus/EventDispatcher.java
@@ -0,0 +1,145 @@
+package dev.zontreck.eventsbus;
+
+import dev.zontreck.eventsbus.annotations.EventSubscriber;
+import dev.zontreck.eventsbus.annotations.Priority;
+import dev.zontreck.eventsbus.annotations.SingleshotEvent;
+import dev.zontreck.eventsbus.annotations.Subscribe;
+import dev.zontreck.eventsbus.events.EventBusReadyEvent;
+import dev.zontreck.eventsbus.events.ResetEventBusEvent;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class EventDispatcher
+{
+ private static List singleshot = new ArrayList<>();
+ private static List> subscribers = new ArrayList<>();
+
+ /**
+ * Scans every Java class that is currently loaded. It then checks for Subscribe, and a proper parameter before posting the Event.
+ * The Event will only be posted if not cancelled using {@link Event#setCancelled(boolean)} and that {@link Subscribe#allowCancelled()} allows.
+ * @param event The event to post
+ * @return True if cancelled.
+ */
+
+ public static boolean Post(Event event)
+ {
+ for(PriorityLevel level : PriorityLevel.values())
+ {
+
+ for(Class> clazz : subscribers)
+ {
+ for(Method M :clazz.getMethods())
+ {
+ if(!M.isAnnotationPresent(Subscribe.class)) continue;
+
+ Subscribe subscriber = M.getAnnotation(Subscribe.class);
+
+
+ boolean canPost=true;
+ Class> param = M.getParameterTypes()[0];
+ if(param == event.getClass())
+ {
+ if(M.isAnnotationPresent(SingleshotEvent.class))
+ {
+ if(singleshot.contains(M))
+ {
+ canPost=false;
+ }
+ }
+ } else canPost=false;
+
+ PriorityLevel eventPriotityLevel= PriorityLevel.HIGH; // Default
+
+ if(M.isAnnotationPresent(Priority.class))
+ {
+ Priority prio = M.getAnnotation(Priority.class);
+ eventPriotityLevel=prio.Level();
+ }
+
+ if(level != eventPriotityLevel)
+ {
+ canPost=false;
+ }
+
+
+ // Dispatch the event now
+
+ try {
+ if(event.isCancelled() && !subscriber.allowCancelled())
+ continue;
+ else
+ M.invoke(null, event);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+ }
+ }
+
+ return event.isCancelled();
+ }
+
+
+ /**
+ * Scan all event subscribers
+ */
+ public static void Scan()
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ Package[] packages = Package.getPackages();
+
+ List> loaded = new ArrayList<>();
+
+ for(Package pkg : packages)
+ {
+ try{
+ String packageName = pkg.getName();
+ Field classesField = ClassLoader.class.getDeclaredField("classes");
+ classesField.setAccessible(true);
+
+ List> classes = (List>) classesField.get(classLoader);
+
+ for(Class> clazz : classes)
+ {
+ if(clazz.getPackage().getName().equalsIgnoreCase(packageName))
+ {
+
+ if(clazz.isAnnotationPresent(EventSubscriber.class))
+ loaded.add(clazz);
+ }
+ }
+
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ subscribers = loaded;
+ }
+
+ /**
+ * Resets the events system.
+ *
+ * This action clears the Singleshot list for the events that should only be invoked once. And rescans all classes incase new classes were dynamically loaded.
+ */
+ public static void Reset()
+ {
+ Post(new ResetEventBusEvent());
+
+ singleshot.clear();
+ Scan();
+ ClassScanner.DoScan();
+
+ Post(new EventBusReadyEvent());
+ }
+}
diff --git a/src/main/java/dev/zontreck/eventsbus/Cancellable.java b/src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java
similarity index 86%
rename from src/main/java/dev/zontreck/eventsbus/Cancellable.java
rename to src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java
index a653b8d..34be386 100644
--- a/src/main/java/dev/zontreck/eventsbus/Cancellable.java
+++ b/src/main/java/dev/zontreck/eventsbus/annotations/Cancellable.java
@@ -1,4 +1,4 @@
-package dev.zontreck.eventsbus;
+package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/src/main/java/dev/zontreck/eventsbus/Subscribe.java b/src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java
similarity index 64%
rename from src/main/java/dev/zontreck/eventsbus/Subscribe.java
rename to src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java
index c25ef17..0ee5023 100644
--- a/src/main/java/dev/zontreck/eventsbus/Subscribe.java
+++ b/src/main/java/dev/zontreck/eventsbus/annotations/EventSubscriber.java
@@ -1,4 +1,4 @@
-package dev.zontreck.eventsbus;
+package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -6,7 +6,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = ElementType.METHOD)
-
-public @interface Subscribe {
+@Target(value = ElementType.TYPE)
+public @interface EventSubscriber {
}
diff --git a/src/main/java/dev/zontreck/eventsbus/Priority.java b/src/main/java/dev/zontreck/eventsbus/annotations/Priority.java
similarity index 76%
rename from src/main/java/dev/zontreck/eventsbus/Priority.java
rename to src/main/java/dev/zontreck/eventsbus/annotations/Priority.java
index d25cd3e..88a4276 100644
--- a/src/main/java/dev/zontreck/eventsbus/Priority.java
+++ b/src/main/java/dev/zontreck/eventsbus/annotations/Priority.java
@@ -1,4 +1,6 @@
-package dev.zontreck.eventsbus;
+package dev.zontreck.eventsbus.annotations;
+
+import dev.zontreck.eventsbus.PriorityLevel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/src/main/java/dev/zontreck/eventsbus/SingleshotEvent.java b/src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java
similarity index 86%
rename from src/main/java/dev/zontreck/eventsbus/SingleshotEvent.java
rename to src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java
index 46144fe..6e8d612 100644
--- a/src/main/java/dev/zontreck/eventsbus/SingleshotEvent.java
+++ b/src/main/java/dev/zontreck/eventsbus/annotations/SingleshotEvent.java
@@ -1,4 +1,4 @@
-package dev.zontreck.eventsbus;
+package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java b/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java
new file mode 100644
index 0000000..9facb6e
--- /dev/null
+++ b/src/main/java/dev/zontreck/eventsbus/annotations/Subscribe.java
@@ -0,0 +1,18 @@
+package dev.zontreck.eventsbus.annotations;
+
+import dev.zontreck.eventsbus.Event;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = ElementType.METHOD)
+
+public @interface Subscribe {
+ /**
+ * Marks that the subscribed method will not receive the signal if the event was cancelled with {@link Event#setCancelled(boolean)}
+ */
+ boolean allowCancelled();
+}
diff --git a/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java b/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java
index 7645ac2..20f2e74 100644
--- a/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java
+++ b/src/main/java/dev/zontreck/eventsbus/events/ResetEventBusEvent.java
@@ -1,6 +1,6 @@
package dev.zontreck.eventsbus.events;
-import dev.zontreck.eventsbus.Cancellable;
+import dev.zontreck.eventsbus.annotations.Cancellable;
import dev.zontreck.eventsbus.Event;
/**