diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java index 5529e4a..096205d 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java @@ -16,7 +16,6 @@ import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.lang.reflect.InvocationTargetException; import java.util.*; /** @@ -253,12 +252,12 @@ public class MobFamily { // Below require variant class to be defined final EntityType.Builder entityTypeBuilder = makeEntityTypeBuilder( parentFamily.replaceableTypes[0] ); - bestiaryInfo = makeBestiaryInfo( entityTypeBuilder ); + bestiaryInfo = AnnotationHelper.getBestiaryInfo( this, entityTypeBuilder ); // Initialize deferred registry objects entityType = SMEntities.register( name.toLowerCase( Locale.ROOT ), entityTypeBuilder ); spawnEgg = SMItems.registerSpawnEgg( entityType, parentFamily.eggBaseColor, bestiaryInfo.eggSpotsColor ); - injectEntityType(); + AnnotationHelper.injectEntityTypeHolder( this ); } /** Finds the entity class based on a standard format. */ @@ -272,28 +271,12 @@ public class MobFamily { } } - /** Calls on this species' entity class to generate its bestiary info. */ - private BestiaryInfo makeBestiaryInfo( EntityType.Builder entityTypeBuilder ) { - try { - return AnnotationHelper.getBestiaryInfo( this, entityTypeBuilder ); - } - catch( IllegalAccessException | NoSuchMethodException | InvocationTargetException ex ) { - throw new RuntimeException( "Entity class for " + name + " has invalid bestiary info method", ex ); - } - } - /** * Builds a deep copy of an entity type with a different entity constructor. * Leaves the new entity type "un-built" so it can be further modified, if needed. */ private EntityType.Builder makeEntityTypeBuilder( EntityType original ) { - final EntityType.IFactory factory; - try { - factory = AnnotationHelper.getEntityFactory( this ); - } - catch( NoSuchMethodException ex ) { - throw new RuntimeException( "Entity class for " + name + " has no valid constructors", ex ); - } + final EntityType.IFactory factory = AnnotationHelper.getEntityFactory( this ); final EntityType.Builder clone = EntityType.Builder.of( factory, original.getCategory() ); if( !original.canSummon() ) clone.noSummon(); @@ -307,15 +290,5 @@ public class MobFamily { .clientTrackingRange( original.clientTrackingRange() ).updateInterval( original.updateInterval() ) .setShouldReceiveVelocityUpdates( original.trackDeltas() ); } - - /** Calls on this species' entity class to generate its bestiary info. */ - private void injectEntityType() { - try { - AnnotationHelper.injectEntityTypeHolder( this ); - } - catch( IllegalAccessException ex ) { - throw new RuntimeException( "Entity class for " + name + " has invalid entity type holder", ex ); - } - } } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java index 6d9402f..4f34ea6 100644 --- a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java +++ b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java @@ -10,8 +10,6 @@ import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; -import java.lang.reflect.InvocationTargetException; - public class SMEntities { public static final DeferredRegister> REGISTRY = DeferredRegister.create( ForgeRegistries.ENTITIES, SpecialMobs.MOD_ID ); @@ -24,18 +22,8 @@ public class SMEntities { /** Sets the default attributes for entity types, such as max health, attack damage etc. */ public static void createAttributes( EntityAttributeCreationEvent event ) { // Bestiary-generated entities - for( MobFamily.Species variant : MobFamily.getAllSpecies() ) - createSpeciesAttributes( event, variant ); - } - - /** Builds the attributes for a specific entity species. */ - private static void createSpeciesAttributes( EntityAttributeCreationEvent event, MobFamily.Species species ) { - try { + for( MobFamily.Species species : MobFamily.getAllSpecies() ) event.put( species.entityType.get(), AnnotationHelper.createAttributes( species ) ); - } - catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { - throw new RuntimeException( "Entity class for " + species.name + " has invalid attribute creation method", ex ); - } } /** Sets the natural spawn placement rules for entity types. */ diff --git a/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java b/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java index 8d1a893..5023ae9 100644 --- a/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java +++ b/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java @@ -12,57 +12,85 @@ import javax.annotation.ParametersAreNonnullByDefault; import java.lang.annotation.Annotation; import java.lang.reflect.*; +/** + * Provides helper methods to handle annotation processing through reflection. + */ @ParametersAreNonnullByDefault public final class AnnotationHelper { //--------------- PRETTY HELPER METHODS ---------------- /** Creates an entity factory from a special mob species. Throws an exception if anything goes wrong. */ - public static void injectEntityTypeHolder( MobFamily.Species species ) throws IllegalAccessException { - final Field field = getFieldOptional( species.entityClass, SpecialMob.TypeHolder.class ); - if( field != null ) field.set( null, species.entityType ); + public static void injectEntityTypeHolder( MobFamily.Species species ) { + try { + final Field field = getFieldOptional( species.entityClass, SpecialMob.TypeHolder.class ); + if( field != null ) field.set( null, species.entityType ); + } + catch( IllegalAccessException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid entity type holder", ex ); + } } /** Creates an entity factory from a special mob species. Throws an exception if anything goes wrong. */ - public static EntityType.IFactory getEntityFactory( MobFamily.Species species ) - throws NoSuchMethodException { - final Constructor constructor = getConstructor( species.entityClass, SpecialMob.Constructor.class ); - return ( entityType, world ) -> { - try { - return constructor.newInstance( entityType, world ); - } - catch( InstantiationException | IllegalAccessException | InvocationTargetException ex ) { - throw new RuntimeException( "Class for " + constructor.getDeclaringClass().getName() + " has invalid constructor", ex ); - } - }; + public static EntityType.IFactory getEntityFactory( MobFamily.Species species ) { + try { + final Constructor constructor = getConstructor( species.entityClass, SpecialMob.Constructor.class ); + return ( entityType, world ) -> { + try { + return constructor.newInstance( entityType, world ); + } + catch( InstantiationException | IllegalAccessException | InvocationTargetException ex ) { + throw new RuntimeException( "Class for " + constructor.getDeclaringClass().getName() + " has invalid constructor", ex ); + } + }; + } + catch( NoSuchMethodException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has no valid constructors", ex ); + } } /** Gets bestiary info from a special mob species. Throws an exception if anything goes wrong. */ - public static BestiaryInfo getBestiaryInfo( MobFamily.Species species, EntityType.Builder entityType ) - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - return (BestiaryInfo) getMethod( species.entityClass, SpecialMob.BestiaryInfoSupplier.class ).invoke( null, entityType ); + public static BestiaryInfo getBestiaryInfo( MobFamily.Species species, EntityType.Builder entityType ) { + try { + return (BestiaryInfo) getMethod( species.entityClass, SpecialMob.BestiaryInfoSupplier.class ).invoke( null, entityType ); + } + catch( IllegalAccessException | NoSuchMethodException | InvocationTargetException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid bestiary info method", ex ); + } } /** Creates an attribute modifier map from a special mob species. Throws an exception if anything goes wrong. */ - public static AttributeModifierMap createAttributes( MobFamily.Species species ) - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - return ((AttributeModifierMap.MutableAttribute) getMethod( species.entityClass, SpecialMob.AttributeCreator.class ) - .invoke( null )).build(); + public static AttributeModifierMap createAttributes( MobFamily.Species species ) { + try { + return ((AttributeModifierMap.MutableAttribute) getMethod( species.entityClass, SpecialMob.AttributeCreator.class ) + .invoke( null )).build(); + } + catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid attribute creation method", ex ); + } } /** Gets the translations from a special mob species. Throws an exception if anything goes wrong. */ - public static String[] getTranslations( MobFamily.Species species ) - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - return (String[]) getMethod( species.entityClass, SpecialMob.LanguageProvider.class ) - .invoke( null, species.entityType.get().getDescriptionId() ); + public static String[] getTranslations( MobFamily.Species species ) { + try { + return (String[]) getMethod( species.entityClass, SpecialMob.LanguageProvider.class ) + .invoke( null, species.entityType.get().getDescriptionId() ); + } + catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid language provider method", ex ); + } } /** Builds a loot table from a special mob species. Throws an exception if anything goes wrong. */ - public static LootTableBuilder buildLootTable( MobFamily.Species species ) - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - final LootTableBuilder builder = new LootTableBuilder(); - getMethod( species.entityClass, SpecialMob.LootTableProvider.class ).invoke( null, builder ); - return builder; + public static LootTableBuilder buildLootTable( MobFamily.Species species ) { + try { + final LootTableBuilder builder = new LootTableBuilder(); + getMethod( species.entityClass, SpecialMob.LootTableProvider.class ).invoke( null, builder ); + return builder; + } + catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid loot table builder method", ex ); + } } diff --git a/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java b/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java index a4d8e80..9f4705c 100644 --- a/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java +++ b/src/main/java/fathertoast/specialmobs/datagen/SMLanguageProvider.java @@ -7,7 +7,6 @@ import fathertoast.specialmobs.common.util.References; import net.minecraft.data.DataGenerator; import net.minecraftforge.common.data.LanguageProvider; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; @@ -45,7 +44,7 @@ public class SMLanguageProvider extends LanguageProvider { // Bestiary-generated translations for( MobFamily.Species species : MobFamily.getAllSpecies() ) { - final String[] speciesTranslations = getTranslations( species ); + final String[] speciesTranslations = AnnotationHelper.getTranslations( species ); String[] spawnEggTranslations = format( spawnEggTranslationPattern, speciesTranslations ); spawnEggTranslations[0] = species.spawnEgg.get().getDescriptionId(); @@ -81,16 +80,6 @@ public class SMLanguageProvider extends LanguageProvider { SpecialMobs.LOG.info( "Translation key verification complete!" ); } - /** Gets the translations for a specific entity species. */ - private static String[] getTranslations( MobFamily.Species species ) { - try { - return AnnotationHelper.getTranslations( species ); - } - catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { - throw new RuntimeException( "Entity class for " + species.name + " has invalid language provider method", ex ); - } - } - /** Applies single argument string formats 1:1 given an array of formats and an array of arguments. */ private static String[] format( String[] formats, String[] args ) { final String[] formatted = new String[formats.length]; diff --git a/src/main/java/fathertoast/specialmobs/datagen/SMLootTableProvider.java b/src/main/java/fathertoast/specialmobs/datagen/SMLootTableProvider.java index d1ffaf5..bde510b 100644 --- a/src/main/java/fathertoast/specialmobs/datagen/SMLootTableProvider.java +++ b/src/main/java/fathertoast/specialmobs/datagen/SMLootTableProvider.java @@ -11,12 +11,14 @@ import net.minecraft.data.DataGenerator; import net.minecraft.data.LootTableProvider; import net.minecraft.data.loot.EntityLootTables; import net.minecraft.entity.EntityType; -import net.minecraft.loot.*; +import net.minecraft.loot.LootParameterSet; +import net.minecraft.loot.LootParameterSets; +import net.minecraft.loot.LootTable; +import net.minecraft.loot.ValidationTracker; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.RegistryObject; import javax.annotation.ParametersAreNonnullByDefault; -import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; @@ -54,17 +56,8 @@ public class SMLootTableProvider extends LootTableProvider { @Override protected void addTables() { // Bestiary-generated tables - for( MobFamily.Species variant : MobFamily.getAllSpecies() ) addTable( variant ); - } - - /** Builds the loot table for a specific entity species. */ - private void addTable( MobFamily.Species species ) { - try { + for( MobFamily.Species species : MobFamily.getAllSpecies() ) add( species.entityType.get(), AnnotationHelper.buildLootTable( species ).toLootTable() ); - } - catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { - throw new RuntimeException( "Entity class for " + species.name + " has invalid loot table builder method", ex ); - } } /** Supplies the entity types this loot table provider will be used for. */