diff --git a/specter-core/src/main/java/dev/spiritstudios/specter/api/core/util/ReflectionHelper.java b/specter-core/src/main/java/dev/spiritstudios/specter/api/core/util/ReflectionHelper.java index 7aa388a..748293f 100644 --- a/specter-core/src/main/java/dev/spiritstudios/specter/api/core/util/ReflectionHelper.java +++ b/specter-core/src/main/java/dev/spiritstudios/specter/api/core/util/ReflectionHelper.java @@ -2,9 +2,11 @@ import org.objectweb.asm.tree.AnnotationNode; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; +import java.util.Optional; /** * A bunch of utilities to reduce boilerplate reflection code. @@ -125,6 +127,10 @@ public static void setFieldValue(Object instance, Field field, Object value) { } } + public static Optional getAnnotation(Field field, Class annotationClass) { + return Optional.ofNullable(field.getAnnotation(annotationClass)); + } + @SuppressWarnings("unchecked") public static T getAnnotationValue(AnnotationNode annotation, String key, T defaultValue) { if (annotation == null || annotation.values == null) return defaultValue; diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockEntityTypeRegistrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockEntityTypeRegistrar.java index e498701..726475e 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockEntityTypeRegistrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockEntityTypeRegistrar.java @@ -9,4 +9,9 @@ public interface BlockEntityTypeRegistrar extends MinecraftRegistrar> getRegistry() { return Registries.BLOCK_ENTITY_TYPE; } + + @Override + default Class> getObjectType() { + return Registrar.fixGenerics(BlockEntityType.class); + } } diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockRegistrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockRegistrar.java index e70e02a..daeda61 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockRegistrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/BlockRegistrar.java @@ -19,6 +19,11 @@ default Registry getRegistry() { return Registries.BLOCK; } + @Override + default Class getObjectType() { + return Block.class; + } + @Override default void register(String name, String namespace, Block object, Field field) { Registry.register(getRegistry(), Identifier.of(namespace, name), object); diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/EntityTypeRegistrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/EntityTypeRegistrar.java index 590a7ee..530fdb4 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/EntityTypeRegistrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/EntityTypeRegistrar.java @@ -9,4 +9,9 @@ public interface EntityTypeRegistrar extends MinecraftRegistrar> { default Registry> getRegistry() { return Registries.ENTITY_TYPE; } + + @Override + default Class> getObjectType() { + return Registrar.fixGenerics(EntityType.class); + } } diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/ItemRegistrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/ItemRegistrar.java index 7e0729d..3fcee98 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/ItemRegistrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/ItemRegistrar.java @@ -9,4 +9,9 @@ public interface ItemRegistrar extends MinecraftRegistrar { default Registry getRegistry() { return Registries.ITEM; } + + @Override + default Class getObjectType() { + return Item.class; + } } diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/Registrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/Registrar.java index 8cd96c1..929020c 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/Registrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/Registrar.java @@ -8,7 +8,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; /** * Automatically run a function on each object using reflection. @@ -32,6 +31,15 @@ static void process(Class> clazz, String namespace) { registrar.init(namespace); } + /** + * Workaround for Java's type erasure. + * Use this if {@link T} has a generic type of ?. + */ + @SuppressWarnings("unchecked") + static Class fixGenerics(Class clazz) { + return (Class) clazz; + } + /** * Register an object to the registry. * @@ -42,6 +50,14 @@ static void process(Class> clazz, String namespace) { */ void register(String name, String namespace, T object, Field field); + /** + * Get the type of object to register. + * If {@link T} has a generic type of ?, use {@link Registrar#fixGenerics(Class)} to force the correct type. + * + * @return The type of object to register + */ + Class getObjectType(); + /** * Initialize the registrar and register all objects. * Do not call this method directly, use {@link Registrar#process(Class, String)} instead. @@ -50,20 +66,15 @@ static void process(Class> clazz, String namespace) { */ @ApiStatus.Internal default void init(String namespace) { - for (Field field : this.getClass().getDeclaredFields()) { - if (!Modifier.isStatic(field.getModifiers()) || field.isAnnotationPresent(Ignore.class)) continue; + ReflectionHelper.forEachStaticField(this.getClass(), getObjectType(), (value, name, field) -> { + if (field.isAnnotationPresent(Ignore.class)) return; - T value = ReflectionHelper.getFieldValue(field); - if (value == null || !field.getType().isAssignableFrom(value.getClass())) continue; - - String name = field.getName().toLowerCase(); - if (field.isAnnotationPresent(Name.class)) { - Name nameAnnotation = field.getAnnotation(Name.class); - name = nameAnnotation.value(); - } + String objectName = ReflectionHelper.getAnnotation(field, Name.class) + .map(Name::value) + .orElseGet(name::toLowerCase); - register(name, namespace, value, field); - } + register(objectName, namespace, value, field); + }); } /** diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/SoundEventRegistrar.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/SoundEventRegistrar.java index 5e291cd..0ee7ff3 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/SoundEventRegistrar.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/registration/SoundEventRegistrar.java @@ -1,5 +1,6 @@ package dev.spiritstudios.specter.api.registry.registration; +import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; @@ -15,4 +16,14 @@ public interface SoundEventRegistrar extends MinecraftRegistrar { default void register(String name, String namespace, SoundEvent object, Field field) { Registry.register(getRegistry(), Identifier.of(namespace, name.replace('-', '.')), object); } + + @Override + default Registry getRegistry() { + return Registries.SOUND_EVENT; + } + + @Override + default Class getObjectType() { + return SoundEvent.class; + } }