diff --git a/plutolib/src/main/java/cz/tefek/pluto/Pluto.java b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java
new file mode 100644
index 0000000..77fc524
--- /dev/null
+++ b/plutolib/src/main/java/cz/tefek/pluto/Pluto.java
@@ -0,0 +1,6 @@
+package cz.tefek.pluto;
+
+public class Pluto
+{
+ public static final boolean DEBUG_MODE = Boolean.valueOf(System.getProperty("cz.tefek.pluto.debug"));
+}
diff --git a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java
index 4f498c4..2d31dc4 100644
--- a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java
+++ b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEvent.java
@@ -1,25 +1,25 @@
-package cz.tefek.pluto.eventsystem.staticmode;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import cz.tefek.pluto.eventsystem.EventData;
-
-@Retention(RUNTIME)
-@Target(ANNOTATION_TYPE)
-/**
- * @author 493msi
- *
- */
-public @interface StaticPlutoEvent
-{
- /**
- * This actually does nothing. ¯\_(ツ)_/¯ Well, you can use it for improved
- * code readability.
- *
- */
- Class> passingParamClass() default EventData.class;
-}
+package cz.tefek.pluto.eventsystem.staticmode;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import cz.tefek.pluto.eventsystem.EventData;
+
+/**
+ * @author 493msi
+ *
+ */
+@Retention(RUNTIME)
+@Target(ANNOTATION_TYPE)
+public @interface StaticPlutoEvent
+{
+ /**
+ * This actually does nothing. ¯\_(ツ)_/¯ Well, you can use it for improved
+ * code readability.
+ *
+ */
+ Class> passingParamClass() default EventData.class;
+}
diff --git a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java
index 50670c4..f069754 100644
--- a/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java
+++ b/plutolib/src/main/java/cz/tefek/pluto/eventsystem/staticmode/StaticPlutoEventManager.java
@@ -1,228 +1,223 @@
-package cz.tefek.pluto.eventsystem.staticmode;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import cz.tefek.pluto.eventsystem.EventData;
-import cz.tefek.pluto.io.logger.Logger;
-import cz.tefek.pluto.io.logger.SmartSeverity;
-
-/**
- * A universal event manager. Register an event {@link Annotation} of your
- * choice (must be annotated with {@link StaticPlutoEvent @Event}), then
- * annotate some public static method and you are done! Now you can trigger the
- * callbacks with ease. Multiple per-method events are possible! Note that
- * event callbacks require a data-passing parameter
- * (extends {@link EventData}). The method will not be invoked
- * otherwise!
- *
- * @author 493msi
- *
- */
-public class StaticPlutoEventManager
-{
- private static Map, List> eventRegistry = new HashMap, List>();
- private static List orphans = new ArrayList();
-
- public static void registerEventHandler(Class> clazz)
- {
- Method[] methods = clazz.getMethods();
-
- int methodsFound = 0;
-
- for (Method method : methods)
- {
- // The callback method must be static and public!
- if (!(Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers())))
- {
- continue;
- }
-
- for (Annotation annotation : method.getDeclaredAnnotations())
- {
- if (annotation.annotationType().getAnnotation(StaticPlutoEvent.class) != null)
- {
- methodsFound++;
-
- var parentAnnotation = eventRegistry.get(annotation.annotationType());
-
- // Find a parent annotation.
- if (parentAnnotation != null)
- {
- parentAnnotation.add(method);
- }
- // No parent annotation and fix for methods with 2+ event
- // annotations.
- else if (!orphans.contains(method))
- {
- orphans.add(method);
- }
- }
- }
- }
-
- Logger.log(SmartSeverity.EVENT_PLUS, "Event handler " + clazz.getCanonicalName() + " scan found " + methodsFound + " method callback(s).");
- }
-
- public static void registerEvent(Class extends Annotation> annotation)
- {
- // @Event is necessary.
- if (annotation.getAnnotation(StaticPlutoEvent.class) != null)
- {
- if (eventRegistry.containsKey(annotation))
- {
- Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is already registered!");
- return;
- }
- else
- {
- eventRegistry.put(annotation, new ArrayList());
-
- Logger.log(SmartSeverity.EVENT_PLUS, "Event " + annotation.getCanonicalName() + " successfully registered!");
-
- short retroactivelyFound = 0;
-
- // Let's check all existing event Methods for this event.
- for (Entry, List> entry : eventRegistry.entrySet())
- {
- // Checking the Method list for this event would make no
- // sense.
- if (annotation.equals(entry.getKey()))
- {
- continue;
- }
-
- for (Method method : entry.getValue())
- {
- // Just in case.
- if (method.isAnnotationPresent(annotation))
- {
- eventRegistry.get(annotation).add(method);
- retroactivelyFound++;
- }
- }
- }
-
- Logger.log(SmartSeverity.EVENT_PLUS, "Retroactive method checking found " + retroactivelyFound + " item(s).");
-
- // Let's check the Method orphanage for some potential
- // candidates.
-
- short orphansFound = 0;
-
- int orphansBefore = orphans.size();
-
- List foundParents = new ArrayList();
-
- for (Method method : orphans)
- {
- if (method.isAnnotationPresent(annotation))
- {
- foundParents.add(method);
-
- // No duplicates.
- if (!eventRegistry.get(annotation).contains(method))
- {
- eventRegistry.get(annotation).add(method);
- orphansFound++;
- }
- }
- }
-
- orphans.removeAll(foundParents);
-
- Logger.log(SmartSeverity.EVENT_PLUS, orphansFound + " orphan method(s) was/were bound and " + (orphansBefore - orphans.size()) + " removed from the storage!");
- }
- }
- else
- {
- Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is not annotated with @Event, can't register it.");
- }
- }
-
- public static void fireEvent(Class extends Annotation> event, EventData data)
- {
- if (event.getAnnotation(StaticPlutoEvent.class) != null)
- {
- List methodList = eventRegistry.get(event);
-
- if (methodList != null)
- {
- for (Method m : methodList)
- {
- // If a method contains more than one parameter, the most
- // viable one will be chosen. Also, methods with no
- // parameters are not valid.
-
- Class>[] params = m.getParameterTypes();
-
- Class> mostSuitableParam = null;
- EventData[] paramOut = new EventData[params.length];
-
- if (params.length == 0)
- {
- Logger.log(SmartSeverity.EVENT_WARNING, "Method " + m.toGenericString() + " has no parameters, will not be invoked by event!");
- }
-
- for (int i = 0; i < params.length; i++)
- {
- Class> parameter = params[i];
-
- if (!EventData.class.isAssignableFrom(parameter))
- {
- Logger.log(SmartSeverity.EVENT_ERROR, "Method " + m.toGenericString() + " contains invalid parameters. Only EventData instances are permitted.");
- mostSuitableParam = null;
- break;
- }
-
- if (mostSuitableParam == null && parameter.isInstance(data))
- {
- mostSuitableParam = parameter;
- paramOut[i] = data;
- }
-
- if (parameter.isInstance(data) && mostSuitableParam.isAssignableFrom(parameter))
- {
- mostSuitableParam = parameter;
- paramOut = new EventData[params.length];
- paramOut[i] = data;
- }
- }
-
- if (mostSuitableParam != null)
- {
- try
- {
- m.invoke(null, (Object[]) paramOut);
- }
- catch (Exception e)
- {
- Logger.logException(e);
- }
- }
- }
- }
- else
- {
- Logger.log(SmartSeverity.EVENT_ERROR, "There is no event like " + event.getCanonicalName() + " registered.");
- }
- }
- else
- {
- Logger.log(SmartSeverity.EVENT_ERROR, event.getCanonicalName() + " is not an event!");
- }
- }
-
- public static void unregisterAll()
- {
- eventRegistry.clear();
- orphans.clear();
- }
-}
+package cz.tefek.pluto.eventsystem.staticmode;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import cz.tefek.pluto.eventsystem.EventData;
+import cz.tefek.pluto.io.logger.Logger;
+import cz.tefek.pluto.io.logger.SmartSeverity;
+
+/**
+ * A universal event manager. Register an event {@link Annotation} of your
+ * choice (must be annotated with {@link StaticPlutoEvent @Event}), then
+ * annotate some public static method and you are done! Now you can trigger the
+ * callbacks with ease. Multiple per-method events are possible! Note that
+ * event callbacks require a data-passing parameter
+ * (extends {@link EventData}). The method will not be invoked
+ * otherwise!
+ *
+ * @author 493msi
+ *
+ */
+public class StaticPlutoEventManager
+{
+ private static Map, List> eventRegistry = new HashMap<>();
+ private static List orphans = new ArrayList<>();
+
+ public static void registerEventHandler(Class> clazz)
+ {
+ Method[] methods = clazz.getMethods();
+
+ int methodsFound = 0;
+
+ for (Method method : methods)
+ {
+ // The callback method must be static and public!
+ if (!(Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers())))
+ {
+ continue;
+ }
+
+ for (Annotation annotation : method.getDeclaredAnnotations())
+ {
+ if (annotation.annotationType().getAnnotation(StaticPlutoEvent.class) != null)
+ {
+ methodsFound++;
+
+ var parentAnnotation = eventRegistry.get(annotation.annotationType());
+
+ // Find a parent annotation.
+ if (parentAnnotation != null)
+ {
+ parentAnnotation.add(method);
+ }
+ // No parent annotation and fix for methods with 2+ event
+ // annotations.
+ else if (!orphans.contains(method))
+ {
+ orphans.add(method);
+ }
+ }
+ }
+ }
+
+ Logger.log(SmartSeverity.EVENT_PLUS, "Event handler " + clazz.getCanonicalName() + " scan found " + methodsFound + " method callback(s).");
+ }
+
+ public static void registerEvent(Class extends Annotation> annotation)
+ {
+ // @Event is necessary.
+ if (annotation.getAnnotation(StaticPlutoEvent.class) != null)
+ {
+ if (eventRegistry.containsKey(annotation))
+ {
+ Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is already registered!");
+ return;
+ }
+
+ eventRegistry.put(annotation, new ArrayList<>());
+
+ Logger.log(SmartSeverity.EVENT_PLUS, "Event " + annotation.getCanonicalName() + " successfully registered!");
+
+ short retroactivelyFound = 0;
+
+ // Let's check all existing event Methods for this event.
+ for (Entry, List> entry : eventRegistry.entrySet())
+ {
+ // Checking the Method list for this event would make no
+ // sense.
+ if (annotation.equals(entry.getKey()))
+ {
+ continue;
+ }
+
+ for (Method method : entry.getValue())
+ {
+ // Just in case.
+ if (method.isAnnotationPresent(annotation))
+ {
+ eventRegistry.get(annotation).add(method);
+ retroactivelyFound++;
+ }
+ }
+ }
+
+ Logger.log(SmartSeverity.EVENT_PLUS, "Retroactive method checking found " + retroactivelyFound + " item(s).");
+
+ // Let's check the Method orphanage for some potential
+ // candidates.
+
+ short orphansFound = 0;
+
+ int orphansBefore = orphans.size();
+
+ List foundParents = new ArrayList<>();
+
+ for (Method method : orphans)
+ {
+ if (method.isAnnotationPresent(annotation))
+ {
+ foundParents.add(method);
+
+ // No duplicates.
+ if (!eventRegistry.get(annotation).contains(method))
+ {
+ eventRegistry.get(annotation).add(method);
+ orphansFound++;
+ }
+ }
+ }
+
+ orphans.removeAll(foundParents);
+
+ Logger.log(SmartSeverity.EVENT_PLUS, orphansFound + " orphan method(s) was/were bound and " + (orphansBefore - orphans.size()) + " removed from the storage!");
+ }
+ else
+ {
+ Logger.log(SmartSeverity.EVENT_ERROR, "Annotation " + annotation.getCanonicalName() + " is not annotated with @Event, can't register it.");
+ }
+ }
+
+ public static void fireEvent(Class extends Annotation> event, EventData data)
+ {
+ if (event.getAnnotation(StaticPlutoEvent.class) != null)
+ {
+ List methodList = eventRegistry.get(event);
+
+ if (methodList != null)
+ {
+ for (Method m : methodList)
+ {
+ // If a method contains more than one parameter, the most
+ // viable one will be chosen. Also, methods with no
+ // parameters are not valid.
+
+ Class>[] params = m.getParameterTypes();
+
+ Class> mostSuitableParam = null;
+ EventData[] paramOut = new EventData[params.length];
+
+ if (params.length == 0)
+ {
+ Logger.log(SmartSeverity.EVENT_WARNING, "Method " + m.toGenericString() + " has no parameters, will not be invoked by event!");
+ }
+
+ for (int i = 0; i < params.length; i++) {
+ Class> parameter = params[i];
+
+ if (!EventData.class.isAssignableFrom(parameter)) {
+ Logger.log(SmartSeverity.EVENT_ERROR, "Method " + m.toGenericString() + " contains invalid parameters. Only EventData instances are permitted.");
+ mostSuitableParam = null;
+ break;
+ }
+
+ if (parameter.isInstance(data))
+ {
+ if (mostSuitableParam == null)
+ {
+ mostSuitableParam = parameter;
+ paramOut[i] = data;
+ }
+ else if (mostSuitableParam.isAssignableFrom(parameter))
+ {
+ mostSuitableParam = parameter;
+ Arrays.fill(paramOut, 0, i, null);
+ paramOut[i] = data;
+ }
+ }
+ }
+
+ if (mostSuitableParam != null)
+ {
+ try
+ {
+ m.invoke(null, (Object[]) paramOut);
+ }
+ catch (Exception e)
+ {
+ Logger.logException(e);
+ }
+ }
+ }
+ }
+ else
+ {
+ Logger.log(SmartSeverity.EVENT_ERROR, "There is no event like " + event.getCanonicalName() + " registered.");
+ }
+ }
+ else
+ {
+ Logger.log(SmartSeverity.EVENT_ERROR, event.getCanonicalName() + " is not an event!");
+ }
+ }
+
+ public static void unregisterAll()
+ {
+ eventRegistry.clear();
+ orphans.clear();
+ }
+}
diff --git a/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java b/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java
index 818926d..f7e9b07 100644
--- a/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java
+++ b/plutolib/src/main/java/cz/tefek/pluto/io/asl/resource/ResourceHelper.java
@@ -1,7 +1,10 @@
package cz.tefek.pluto.io.asl.resource;
+import java.io.IOException;
+import java.nio.file.Files;
+
/**
- * Doesn't do much right now. Just holds the default resource location.
+ * Helper functions for {@link ResourceAddress}es.
*
* @author 493msi
*/
@@ -9,4 +12,19 @@ public class ResourceHelper
{
public static final String GLOBAL_ROOT = "";
public static final String DEFAULT_RESOURCE_ROOT = GLOBAL_ROOT + "data";
+
+ /**
+ * Retrieves the size of the file denoted by {@link ResourceAddress}
+ *
+ * @param addr The input {@link ResourceAddress}
+ *
+ * @throws IOException On I/O errors.
+ *
+ * @return the file size
+ * @since 0.3
+ */
+ public static long fileSize(ResourceAddress addr) throws IOException
+ {
+ return Files.size(addr.toNIOPath());
+ }
}