diff --git a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java index 2f4ae21..9a22b61 100644 --- a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java +++ b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java @@ -10,7 +10,6 @@ import fathertoast.specialmobs.common.entity.witherskeleton.NinjaWitherSkeletonE import mcp.MethodsReturnNonnullByDefault; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.entity.SpriteRenderer; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -58,12 +57,12 @@ public class ClientRegister { registerSpeciesRenderer( NinjaSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new ); registerSpeciesRenderer( NinjaWitherSkeletonEntity.SPECIES, NinjaSkeletonRenderer::new ); registerSpeciesRenderer( CorporealShiftGhastEntity.SPECIES, CorporealShiftGhastRenderer::new ); - + // Other registerSpriteRenderer( SMEntities.CORPOREAL_FIREBALL.get(), game, 3.0F, true ); } - private static void registerFamilyRenderers( MobFamily family, IRenderFactory renderFactory ) { + private static void registerFamilyRenderers( MobFamily family, IRenderFactory renderFactory ) { RenderingRegistry.registerEntityRenderingHandler( family.vanillaReplacement.entityType.get(), renderFactory ); for( MobFamily.Species species : family.variants ) registerSpeciesRenderer( species, renderFactory ); @@ -72,9 +71,9 @@ public class ClientRegister { private static void registerSpeciesRenderer( MobFamily.Species species, IRenderFactory renderFactory ) { RenderingRegistry.registerEntityRenderingHandler( species.entityType.get(), renderFactory ); } - - private static void registerSpriteRenderer(EntityType entityType, Supplier minecraftSupplier, float scale, boolean fullBright) { + + private static void registerSpriteRenderer( EntityType entityType, Supplier minecraftSupplier, float scale, boolean fullBright ) { ItemRenderer itemRenderer = minecraftSupplier.get().getItemRenderer(); - RenderingRegistry.registerEntityRenderingHandler(entityType, (renderManager) -> new SpriteRenderer<>(renderManager, itemRenderer, scale, fullBright)); + RenderingRegistry.registerEntityRenderingHandler( entityType, ( renderManager ) -> new SpriteRenderer<>( renderManager, itemRenderer, scale, fullBright ) ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/BestiaryInfo.java b/src/main/java/fathertoast/specialmobs/common/bestiary/BestiaryInfo.java index e1b5925..0cb93ab 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/BestiaryInfo.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/BestiaryInfo.java @@ -1,8 +1,30 @@ package fathertoast.specialmobs.common.bestiary; +import fathertoast.specialmobs.common.config.util.AttributeEntry; +import fathertoast.specialmobs.common.config.util.AttributeList; +import fathertoast.specialmobs.common.config.util.ConfigUtil; +import fathertoast.specialmobs.common.config.util.RegistryEntryList; +import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.util.References; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.Attributes; +import net.minecraft.potion.Effect; +import net.minecraft.potion.Effects; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.*; + +/** + * This class serves solely to store data for mob species in an organized way, providing builder methods as applicable. + * The bulk of bestiary info is default config settings. + */ public class BestiaryInfo { - public enum BaseWeight { + public enum DefaultWeight { DEFAULT( 600 ), DISABLED( 0 ), LOWEST( DEFAULT.value / 8 ), @@ -12,103 +34,555 @@ public class BestiaryInfo { public final int value; - BaseWeight( int v ) { value = v; } + DefaultWeight( int v ) { value = v; } } - //TODO default themes - - // public static final EnvironmentListConfig DEFAULT_THEME_FIRE = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "savanna", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "mesa", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetDimension( DimensionType.NETHER, BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "ice", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "frozen", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "cold", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "taiga_cold", BestiaryInfo.BASE_WEIGHT_RARE ) - // ); - // - // public static final EnvironmentListConfig DEFAULT_THEME_ICE = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "ice", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "frozen", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "cold", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "taiga_cold", BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "savanna", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "mesa", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetDimension( DimensionType.NETHER, BestiaryInfo.BASE_WEIGHT_RARE ) - // ); - // - // public static final EnvironmentListConfig DEFAULT_THEME_FOREST = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "swamp", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "forest", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "birch_forest", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "roofed_forest", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "jungle", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "taiga", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "redwood_taiga", BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "ice", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "stone", BestiaryInfo.BASE_WEIGHT_RARE ) - // ); - // - // public static final EnvironmentListConfig DEFAULT_THEME_MOUNTAIN = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "extreme", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "smaller_extreme", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "mesa", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "ice_mountains", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiomeGroup( "stone", BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "plains", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "swamp", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "beach", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "cold_beach", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "savanna", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "ice_flats", BestiaryInfo.BASE_WEIGHT_RARE ) - // ); - // - // public static final EnvironmentListConfig DEFAULT_THEME_WATER = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "swamp", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.BEACH, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.DEEP_OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.FROZEN_OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetBiomeGroup( "savanna", BestiaryInfo.BASE_WEIGHT_RARE ), - // new TargetEnvironment.TargetDimension( DimensionType.NETHER, 0 ) - // ); - // - // public static final EnvironmentListConfig DEFAULT_THEME_FISHING = new EnvironmentListConfig( - // new TargetEnvironment.TargetBiomeGroup( "swamp", BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.BEACH, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.DEEP_OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // new TargetEnvironment.TargetBiome( Biomes.FROZEN_OCEAN, BestiaryInfo.BASE_WEIGHT_COMMON ), - // - // new TargetEnvironment.TargetBiomeGroup( "desert", BestiaryInfo.BASE_WEIGHT_UNCOMMON ), - // new TargetEnvironment.TargetBiomeGroup( "savanna", BestiaryInfo.BASE_WEIGHT_UNCOMMON ), - // new TargetEnvironment.TargetBiomeGroup( "mesa", BestiaryInfo.BASE_WEIGHT_UNCOMMON ) - // ); - - // These can be set in the entity class to change these default values. - //public EnvironmentListConfig weightExceptions = new EnvironmentListConfig( ); + public enum Theme { + NONE, + FIRE, ICE, + DESERT, WATER, + FOREST, MOUNTAIN, + FISHING + } + /** The spot color for spawn eggs of this species. The base color is determined by the family. */ public final int eggSpotsColor; - public final BaseWeight weight; + /** The base render scale of this species. */ + public final float baseScale; - public BestiaryInfo( int eggColor ) { this( eggColor, BaseWeight.DEFAULT ); } + /** The default species weight. */ + public final DefaultWeight defaultWeight; + /** The species theme; determines default environment weight exceptions. */ + public final Theme theme; + /** The default species attribute differences compared to their vanilla counterpart. */ + public final AttributeList defaultAttributes; - public BestiaryInfo( int eggColor, BaseWeight baseWeight ) { - eggSpotsColor = eggColor; - weight = baseWeight; + /** The default texture. */ + public final ResourceLocation texture; + /** The default glowing eyes texture. Not applicable for ghasts or families normally rendered at max brightness. */ + public final ResourceLocation eyesTexture; + /** + * The default overlay texture. + * Generally only applicable for bipedal mobs, though this is used as the "shooting" texture for ghasts. + */ + public final ResourceLocation overlayTexture; + + // Special Mob Data defaults + public final int experience; + public final int healTime; + public final double fallDamageMultiplier; + public final boolean isImmuneToFire; + public final boolean isImmuneToBurning; + public final boolean canBreatheInWater; + public final boolean ignoreWaterPush; + public final boolean isDamagedByWater; + public final boolean allowLeashing; + public final boolean ignorePressurePlates; + public final RegistryEntryList immuneToStickyBlocks; + public final RegistryEntryList immuneToPotions; + public final double rangedAttackDamage; + public final double rangedAttackSpread; + public final double rangedWalkSpeed; + public final int rangedAttackCooldown; + public final int rangedAttackMaxCooldown; + public final double rangedAttackMaxRange; + + + //--------------- Builder Implementation ---------------- + + public static BestiaryInfo.Builder of( MobFamily.Species species, EntityType.Builder typeBuilder ) { + return new Builder( species, typeBuilder ); } - public BestiaryInfo setTheme() { - return this;//TODO theme builder + private BestiaryInfo( int eggColor, float scale, DefaultWeight weight, Theme spawnTheme, List attributes, + ResourceLocation tex, ResourceLocation eyeTex, ResourceLocation ovrTex, + int xp, int regen, double fallDmg, boolean fireImm, boolean burnImm, boolean drownImm, boolean pushImm, + boolean waterDmg, boolean leash, boolean plateImm, Block[] blockImm, Effect[] effectImm, + double raDmg, double raVar, double raSpd, int raCD, int raMCD, double raRng ) { + eggSpotsColor = eggColor; + baseScale = scale; + + defaultWeight = weight; + theme = spawnTheme; + defaultAttributes = new AttributeList( attributes ); + + texture = tex; + eyesTexture = eyeTex; + overlayTexture = ovrTex; + + experience = xp; + healTime = regen; + fallDamageMultiplier = fallDmg; + isImmuneToFire = fireImm; + isImmuneToBurning = burnImm; + canBreatheInWater = drownImm; + ignoreWaterPush = pushImm; + isDamagedByWater = waterDmg; + allowLeashing = leash; + ignorePressurePlates = plateImm; + immuneToStickyBlocks = new RegistryEntryList<>( ForgeRegistries.BLOCKS, blockImm ); + immuneToPotions = new RegistryEntryList<>( ForgeRegistries.POTIONS, effectImm ); + rangedAttackDamage = raDmg; + rangedAttackSpread = raVar; + rangedWalkSpeed = raSpd; + rangedAttackCooldown = raCD; + rangedAttackMaxCooldown = raMCD; + rangedAttackMaxRange = raRng; + } + + @SuppressWarnings( { "UnusedReturnValue", "unused" } ) + public static final class Builder { + + private final MobFamily.Species owningSpecies; + private final EntityType.Builder entityTypeBuilder; + + // Fields NOT inherited from vanilla replacement + private boolean colorSet; + private int eggSpotsColor; + private DefaultWeight defaultWeight = DefaultWeight.DEFAULT; + private Theme spawnTheme = Theme.NONE; + private final List attributes = new ArrayList<>(); + + // Fields inherited from vanilla replacement (technically also SM Data) + private float baseScale = 1.0F; + private ResourceLocation texture; + private ResourceLocation eyesTexture; + private ResourceLocation overlayTexture; + + // Special Mob Data fields (also inherited) + private int experience = -1; + private int healTime; + private double fallDamageMultiplier = 1.0; + private boolean isImmuneToFire; + private boolean isImmuneToBurning; + private boolean canBreatheInWater; + private boolean ignoreWaterPush; + private boolean isDamagedByWater; + private boolean allowLeashing; + private boolean ignorePressurePlates; + private final ArrayList immuneToStickyBlocks = new ArrayList<>(); + private final ArrayList immuneToPotions = new ArrayList<>(); + private double rangedAttackDamage = -1.0; + private double rangedAttackSpread = -1.0; + private double rangedWalkSpeed = -1.0; + private int rangedAttackCooldown = -1; + private int rangedAttackMaxCooldown = -1; + private double rangedAttackMaxRange = -1.0; + + private Builder( MobFamily.Species species, EntityType.Builder typeBuilder ) { + owningSpecies = species; + entityTypeBuilder = typeBuilder; + + // Special variants should copy many of the vanilla replacement's stats + if( species.specialVariantName != null ) { + final BestiaryInfo parent = species.family.vanillaReplacement.bestiaryInfo; + + baseScale = parent.baseScale; + texture = parent.texture; + eyesTexture = parent.eyesTexture; + overlayTexture = parent.overlayTexture; + + experience = parent.experience; + healTime = parent.healTime; + fallDamageMultiplier = parent.fallDamageMultiplier; + isImmuneToFire = parent.isImmuneToFire; + isImmuneToBurning = parent.isImmuneToBurning; + canBreatheInWater = parent.canBreatheInWater; + ignoreWaterPush = parent.ignoreWaterPush; + isDamagedByWater = parent.isDamagedByWater; + allowLeashing = parent.allowLeashing; + ignorePressurePlates = parent.ignorePressurePlates; + immuneToStickyBlocks.addAll( parent.immuneToStickyBlocks.getEntries() ); + immuneToPotions.addAll( parent.immuneToPotions.getEntries() ); + + rangedAttackDamage = parent.rangedAttackDamage; + rangedAttackSpread = parent.rangedAttackSpread; + rangedWalkSpeed = parent.rangedWalkSpeed; + rangedAttackCooldown = parent.rangedAttackCooldown; + rangedAttackMaxCooldown = parent.rangedAttackMaxCooldown; + rangedAttackMaxRange = parent.rangedAttackMaxRange; + } + } + + BestiaryInfo build() { + // Perform a little verification + if( !colorSet ) + throw new IllegalStateException( "Species " + owningSpecies.name + " has not assigned egg spots color!" ); + if( experience < 0 ) + throw new IllegalStateException( "Family " + owningSpecies.family.name + " has not set the base experience value!" ); + + return new BestiaryInfo( eggSpotsColor, baseScale, defaultWeight, spawnTheme, attributes, texture, eyesTexture, overlayTexture, + experience, healTime, fallDamageMultiplier, isImmuneToFire, isImmuneToBurning, canBreatheInWater, ignoreWaterPush, isDamagedByWater, + allowLeashing, ignorePressurePlates, immuneToStickyBlocks.toArray( new Block[0] ), immuneToPotions.toArray( new Effect[0] ), + rangedAttackDamage, rangedAttackSpread, rangedWalkSpeed, rangedAttackCooldown, rangedAttackMaxCooldown, rangedAttackMaxRange ); + } + + + //--------------- Bestiary ---------------- + + /** Sets the species spawn egg spots color. This MUST be called or the build will throw an exception! */ + public Builder color( int eggColor ) { + eggSpotsColor = eggColor; + colorSet = true; + return this; + } + + /** Sets the species default weight. */ + public Builder weight( DefaultWeight weight ) { + defaultWeight = weight; + return this; + } + + /** Sets the species default environment weight exceptions by theme. */ + public Builder theme( Theme theme ) { + spawnTheme = theme; + return this; + } + + + //--------------- Size ---------------- + + /** Sets the family base render size. Throws an exception if called for a special variant. */ + public Builder familySize( float renderScale ) { + // Do NOT use for special variants; if the render scale is changed, the bounding box should match! + if( owningSpecies.specialVariantName != null ) + throw new IllegalStateException( "Special variant " + owningSpecies.specialVariantName + " cannot set family render scale!" ); + baseScale = renderScale; + return this; + } + + /** Sets the species size - both render scale and bounding box dimensions. */ + public Builder size( float renderScale, float width, float height ) { + baseScale = renderScale; + entityTypeBuilder.sized( width, height ); + return this; + } + + + //--------------- Textures (Vanilla) ---------------- + + /** Sets the species default base, glowing eyes, and overlay textures. */ + public Builder vanillaTexturesAll( String tex, String eyeTex, String ovrTex ) { + return vanillaBaseTexture( tex ).vanillaEyesTexture( eyeTex ).vanillaOverlayTexture( ovrTex ); + } + + /** Sets the species default base and glowing eyes textures. Removes all other textures. */ + public Builder vanillaTextureWithEyes( String tex, String eyeTex ) { + return vanillaBaseTexture( tex ).vanillaEyesTexture( eyeTex ).noOverlayTexture(); + } + + /** Sets the species default base and overlay textures. Removes all other textures. */ + public Builder vanillaTextureWithOverlay( String tex, String ovrTex ) { + return vanillaBaseTexture( tex ).noEyesTexture().vanillaOverlayTexture( ovrTex ); + } + + /** Sets the species default base and animation (overlay) textures. Removes all other textures. */ + public Builder vanillaTextureWithAnimation( String tex, String aniTex ) { return vanillaTextureWithOverlay( tex, aniTex ); } + + /** Sets the species default base texture. Removes all other textures. */ + public Builder vanillaTextureBaseOnly( String tex ) { return vanillaBaseTexture( tex ).noEyesTexture().noOverlayTexture(); } + + /** Sets the species default base texture. */ + private Builder vanillaBaseTexture( String tex ) { return baseTexture( tex == null ? null : new ResourceLocation( tex ) ); } + + /** Sets the species default glowing eyes texture. */ + private Builder vanillaEyesTexture( String eyeTex ) { return eyesTexture( eyeTex == null ? null : new ResourceLocation( eyeTex ) ); } + + /** Sets the species default overlay texture. */ + private Builder vanillaOverlayTexture( String ovrTex ) { return overlayTexture( ovrTex == null ? null : new ResourceLocation( ovrTex ) ); } + + + //--------------- Textures (Auto-selected) ---------------- + + /** Sets the species default base, glowing eyes, and overlay textures. */ + public Builder uniqueTexturesAll() { return uniqueBaseTexture().uniqueEyesTexture().uniqueOverlayTexture(); } + + /** Sets the species default base and glowing eyes textures. Removes all other textures. */ + public Builder uniqueTextureWithEyes() { return uniqueBaseTexture().uniqueEyesTexture().noOverlayTexture(); } + + /** Sets the species default base and overlay textures. Removes all other textures. */ + public Builder uniqueTextureWithOverlay() { return uniqueBaseTexture().noEyesTexture().uniqueOverlayTexture(); } + + /** Sets the species default base and animation (overlay) textures. Removes all other textures. */ + public Builder uniqueTextureWithAnimation() { return uniqueBaseTexture().noEyesTexture().uniqueAnimationTexture(); } + + /** Sets the species default base texture. Removes all other textures. */ + public Builder uniqueTextureBaseOnly() { return uniqueBaseTexture().noEyesTexture().noOverlayTexture(); } + + /** Sets the species default base texture. */ + // Private because we always want to replace all textures when using a unique base + private Builder uniqueBaseTexture() { return baseTexture( getBaseTexture() ); } + + /** Sets the species default glowing eyes texture. */ + public Builder uniqueEyesTexture() { return eyesTexture( getEyesTexture() ); } + + /** Sets the species default overlay texture. */ + public Builder uniqueOverlayTexture() { return overlayTexture( getOverlayTexture() ); } + + /** Sets the species default animation texture (uses the overlay slot). */ + public Builder uniqueAnimationTexture() { return overlayTexture( getShootingTexture() ); } + + /** @return The expected base texture for this builder. */ + private ResourceLocation getBaseTexture() { return toTexture( References.TEXTURE_BASE_SUFFIX ); } + + /** @return The expected eyes texture for this builder. */ + private ResourceLocation getEyesTexture() { return toTexture( References.TEXTURE_EYES_SUFFIX ); } + + /** @return The expected overlay texture for this builder. */ + private ResourceLocation getOverlayTexture() { return toTexture( References.TEXTURE_OVERLAY_SUFFIX ); } + + /** @return The given strings converted to a texture resource location. */ + private ResourceLocation getShootingTexture() { return toTexture( References.TEXTURE_SHOOTING_SUFFIX ); } + + /** @return The given strings converted to a texture resource location. */ + private ResourceLocation toTexture( String suffix ) { + return SpecialMobs.resourceLoc( String.format( References.TEXTURE_FORMAT, + ConfigUtil.camelCaseToLowerUnderscore( owningSpecies.family.name ), + ConfigUtil.camelCaseToLowerUnderscore( owningSpecies.specialVariantName ), suffix ) ); + } + + + //--------------- Textures (Misc/Internal) ---------------- + + /** Removes the species default glowing eyes texture. */ + public Builder noEyesTexture() { return eyesTexture( null ); } + + /** Removes the species default overlay texture. */ + public Builder noOverlayTexture() { return overlayTexture( null ); } + + /** Removes the species default animation texture (uses the overlay slot). */ + public Builder noAnimationTexture() { return noOverlayTexture(); } + + /** Sets the species default base texture. */ + private Builder baseTexture( ResourceLocation tex ) { + texture = tex; + return this; + } + + /** Sets the species default glowing eyes texture. */ + private Builder eyesTexture( ResourceLocation eyeTex ) { + eyesTexture = eyeTex; + return this; + } + + /** Sets the species default overlay texture. */ + private Builder overlayTexture( ResourceLocation ovrTex ) { + overlayTexture = ovrTex; + return this; + } + + + //--------------- Creature Type Templates ---------------- + + /** Sets the standard species stats implied by being undead. */ + public Builder undead() { return effectImmune( Effects.REGENERATION, Effects.POISON ); } + + /** Sets the standard species stats implied by being a spider. */ + public Builder spider() { return webImmune().effectImmune( Effects.POISON ); } + + + //--------------- Special Mob Data ---------------- + + /** Sets the species experience value. */ + public Builder experience( int xp ) { + experience = xp; + return this; + } + + /** Adds a flat amount to the species experience value. */ + public Builder addExperience( int xp ) { return experience( experience + xp ); } + + /** Sets the species heal time. */ + public Builder regen( int time ) { + healTime = time; + return this; + } + + /** Sets the species as fall damage immune. */ + public Builder fallImmune() { return fallDamage( 0.0 ); } + + /** Sets the species fall damage multiplier. */ + public Builder fallDamage( double multiplier ) { + fallDamageMultiplier = multiplier; + return this; + } + + /** Sets the species as fire immune. */ + public Builder fireImmune() { + entityTypeBuilder.fireImmune(); + isImmuneToFire = true; + return this; + } + + /** Sets the species as burning immune. */ + public Builder burnImmune() { + isImmuneToBurning = true; + return this; + } + + /** Sets the species as drowning immune. */ + public Builder drownImmune() { + canBreatheInWater = true; + return this; + } + + /** Sets the species as fluid-pushing immune. */ + public Builder fluidPushImmune() { + ignoreWaterPush = true; + return this; + } + + /** Sets the species as damaged by water. */ + public Builder waterSensitive() { + isDamagedByWater = true; + return this; + } + + /** Sets the species as leashable (can have a lead attached). */ + public Builder leashable() { + allowLeashing = true; + return this; + } + + /** Sets the species as pressure plate immune. */ + public Builder pressurePlateImmune() { + ignorePressurePlates = true; + return this; + } + + /** Sets the block hazards (damaging blocks) the species is immune to. */ + public Builder hazardImmune( Block... hazards ) { + entityTypeBuilder.immuneTo( hazards ); + return this; + } + + /** Sets the species as cobweb immune. */ + public Builder webImmune() { return stickyBlockImmune( Blocks.COBWEB ); } + + /** Sets the species as immune to a specific list of sticky blocks. */ + public Builder stickyBlockImmune( Block... blocks ) { + immuneToStickyBlocks.addAll( Arrays.asList( blocks ) ); + return this; + } + + /** Sets the species as immune to a specific list of effects. */ + public Builder effectImmune( Effect... effects ) { + immuneToPotions.addAll( Arrays.asList( effects ) ); + return this; + } + + + //--------------- Ranged Attacks (Special Mob Data) ---------------- + + /** Sets the species ranged attack stats (for a bow user). */ + public Builder bowAttack( double damage, double spread, double walkSpeed, int cooldown, double range ) { + return rangedDamage( damage ).rangedSpread( spread ).rangedWalkSpeed( walkSpeed ).rangedCooldown( cooldown ).rangedMaxRange( range ); + } + + /** Sets the species ranged attack stats (for a fireball shooter). */ + public Builder fireballAttack( double spread, int charge, int cooldown, double range ) { + return rangedSpread( spread ).rangedCooldown( charge ).rangedMaxCooldown( charge + cooldown ).rangedMaxRange( range ); + } + + /** Sets the species ranged attack stats (for a spit shooter). */ + public Builder spitAttack( double damage, double spread, int cooldown, int extraCooldown, double range ) { + return rangedDamage( damage ).rangedSpread( spread ) + .rangedCooldown( cooldown ).rangedMaxCooldown( cooldown + extraCooldown ).rangedMaxRange( range ); + } + + /** Applies multipliers to the species ranged attack stats (for a spit shooter). */ + public Builder spitAttackMultiplied( double damage, double spread, float cooldown, double range ) { + return multiplyRangedDamage( damage ).multiplyRangedSpread( spread ) + .multiplyRangedCooldown( cooldown ).multiplyRangedMaxCooldown( cooldown ).multiplyRangedMaxRange( range ); + } + + /** Sets the species as unable to use ranged attacks (for any ranged user). */ + public Builder disableRangedAttack() { return rangedMaxRange( 0.0 ); } + + /** Applies a flat modifier to the species ranged attack damage. */ + public Builder addToRangedDamage( double value ) { return rangedDamage( rangedAttackDamage + value ); } + + /** Applies a multiplier to the species ranged attack damage. */ + public Builder multiplyRangedDamage( double value ) { return rangedDamage( rangedAttackDamage * value ); } + + /** Sets the species ranged attack damage. */ + public Builder rangedDamage( double value ) { + if( owningSpecies.specialVariantName != null && rangedAttackDamage < 0.0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedAttackDamage = value; + return this; + } + + /** Applies a multiplier to the species ranged attack spread. */ + public Builder multiplyRangedSpread( double value ) { return rangedSpread( rangedAttackSpread * value ); } + + /** Sets the species ranged attack spread. */ + public Builder rangedSpread( double value ) { + if( owningSpecies.specialVariantName != null && rangedAttackSpread < 0.0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedAttackSpread = value; + return this; + } + + /** Applies a multiplier to the species ranged attack walk speed. */ + public Builder multiplyRangedWalkSpeed( double value ) { return rangedWalkSpeed( rangedWalkSpeed * value ); } + + /** Sets the species ranged attack walk speed. */ + public Builder rangedWalkSpeed( double value ) { + if( owningSpecies.specialVariantName != null && rangedWalkSpeed < 0.0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedWalkSpeed = value; + return this; + } + + /** Applies a multiplier to the species ranged attack cooldown. */ + public Builder multiplyRangedCooldown( float value ) { return rangedCooldown( Math.round( rangedAttackCooldown * value ) ); } + + /** Sets the species ranged attack cooldown. */ + public Builder rangedCooldown( int value ) { + if( owningSpecies.specialVariantName != null && rangedAttackCooldown < 0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedAttackCooldown = value; + return this; + } + + /** Applies a multiplier to the species ranged attack max cooldown. */ + public Builder multiplyRangedMaxCooldown( float value ) { return rangedCooldown( Math.round( rangedAttackMaxCooldown * value ) ); } + + /** Sets the species ranged attack max cooldown. */ + public Builder rangedMaxCooldown( int value ) { + if( owningSpecies.specialVariantName != null && rangedAttackMaxCooldown < 0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedAttackMaxCooldown = value; + return this; + } + + /** Applies a multiplier to the species ranged attack max range. */ + public Builder multiplyRangedMaxRange( double value ) { return rangedMaxRange( rangedAttackMaxRange * value ); } + + /** Sets the species ranged attack max range. */ + public Builder rangedMaxRange( double value ) { + if( owningSpecies.specialVariantName != null && rangedAttackMaxRange < 0.0 ) + throw new IllegalStateException( "Attempted to add inapplicable ranged attack stat!" ); + rangedAttackMaxRange = value; + return this; + } + + + //--------------- Attribute Changes ---------------- + + /** Adds a flat value to the base attribute. Not applicable for the movement speed attribute, use a multiplier instead. */ + public Builder addToAttribute( Attribute attribute, double value ) { + if( attribute == Attributes.MOVEMENT_SPEED ) + throw new IllegalArgumentException( "Do not add flat movement speed!" ); + attributes.add( AttributeEntry.add( attribute, value ) ); + return this; + } + + /** Adds a value multiplier to the base attribute. */ + public Builder multiplyAttribute( Attribute attribute, double value ) { + attributes.add( AttributeEntry.mult( attribute, value ) ); + return this; + } } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java index 321c99a..6ad0b2c 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java @@ -1,5 +1,7 @@ package fathertoast.specialmobs.common.bestiary; +import fathertoast.specialmobs.common.config.family.*; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.core.register.SMEntities; import fathertoast.specialmobs.common.core.register.SMItems; import fathertoast.specialmobs.common.util.AnnotationHelper; @@ -17,6 +19,7 @@ import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.*; +import java.util.function.Function; /** * Special mobs are broken up into distinct 'families', each of which correspond to a type of vanilla mob that can be @@ -26,90 +29,90 @@ import java.util.*; */ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class MobFamily { +public class MobFamily { /** List of all families, generated to make iteration possible. */ - private static final List> FAMILY_LIST = new ArrayList<>(); + private static final List> FAMILY_LIST = new ArrayList<>(); /** List of all species, generated to make iteration more convenient. */ private static final List> SPECIES_LIST; /** Maps each replaceable entity type to the family that replaces it. */ - private static final Map, MobFamily> TYPE_TO_FAMILY_MAP; + private static final Map, MobFamily> TYPE_TO_FAMILY_MAP; // NOTE: When adding a new mob family, do not forget to also register its renderer in the client register! - public static final MobFamily CREEPER = new MobFamily<>( + public static final MobFamily CREEPER = new MobFamily<>( CreeperFamilyConfig::new, "Creeper", "creepers", 0x0DA70B, new EntityType[] { EntityType.CREEPER }, "Dark", "Death", "Dirt", "Doom", "Drowning", "Ender", "Fire", "Gravel", "Jumping", "Lightning", "Mini", /*"Scope",*/ "Skeleton", "Splitting" ); - public static final MobFamily ZOMBIE = new MobFamily<>( + public static final MobFamily ZOMBIE = new MobFamily<>( FamilyConfig::new, "Zombie", "zombies", 0x00AFAF, new EntityType[] { EntityType.ZOMBIE, EntityType.HUSK }, "Brute", "Fire", /*"Fishing",*/ "Giant", "Hungry", "Husk", "MadScientist", "Plague" ); // TODO Drowned family and zombie transform mechanic - public static final MobFamily ZOMBIFIED_PIGLIN = new MobFamily<>(//TODO figure out crossbows + public static final MobFamily ZOMBIFIED_PIGLIN = new MobFamily<>( FamilyConfig::new, "ZombifiedPiglin", "zombified piglins", 0xEA9393, new EntityType[] { EntityType.ZOMBIFIED_PIGLIN }, - "Brute", /*"Fishing",*/ "Giant", "Hungry", "Knight", "Plague", "Vampire" + "Brute", /*"Fishing",*/ "Giant", "Hungry", "Knight", "Plague", "Vampire"//TODO figure out crossbows ); - public static final MobFamily SKELETON = new MobFamily<>( + public static final MobFamily SKELETON = new MobFamily<>( SkeletonFamilyConfig::new, "Skeleton", "skeletons", 0xC1C1C1, new EntityType[] { EntityType.SKELETON, EntityType.STRAY }, "Brute", "Fire", "Gatling", "Giant", "Knight", "Ninja", "Poison", "Sniper", "Spitfire", "Stray" ); - public static final MobFamily WITHER_SKELETON = new MobFamily<>( + public static final MobFamily WITHER_SKELETON = new MobFamily<>( SkeletonFamilyConfig::new, "WitherSkeleton", "wither skeletons", 0x141414, new EntityType[] { EntityType.WITHER_SKELETON }, "Brute", "Gatling", "Giant", "Knight", "Ninja", "Sniper", "Spitfire" ); - public static final MobFamily SLIME = new MobFamily<>( + public static final MobFamily SLIME = new MobFamily<>( SlimeFamilyConfig::new, "Slime", "slimes", 0x51A03E, new EntityType[] { EntityType.SLIME }, "Blackberry", "Blueberry", "Caramel", "Grape", "Lemon", "Strawberry", "Watermelon" ); - public static final MobFamily MAGMA_CUBE = new MobFamily<>( + public static final MobFamily MAGMA_CUBE = new MobFamily<>( FamilyConfig::new, "MagmaCube", "magma cubes", 0x340000, new EntityType[] { EntityType.MAGMA_CUBE }, "Bouncing", "Hardened", "Sticky", "Volatile" ); - public static final MobFamily SPIDER = new MobFamily<>( + public static final MobFamily SPIDER = new MobFamily<>( FamilyConfig::new, "Spider", "spiders", 0x342D27, new EntityType[] { EntityType.SPIDER }, "Baby", "Desert", "Flying", "Giant", "Hungry", "Mother", "Pale", "Poison", /*"Water",*/ "Web", "Witch" ); - public static final MobFamily CAVE_SPIDER = new MobFamily<>( + public static final MobFamily CAVE_SPIDER = new MobFamily<>( FamilyConfig::new, "CaveSpider", "cave spiders", 0x0C424E, new EntityType[] { EntityType.CAVE_SPIDER }, "Baby", "Flying", "Mother", /*"Water",*/ "Web", "Witch" ); - public static final MobFamily SILVERFISH = new MobFamily<>( + public static final MobFamily SILVERFISH = new MobFamily<>( SilverfishFamilyConfig::new, "Silverfish", "silverfish", 0x6E6E6E, new EntityType[] { EntityType.SILVERFISH }, "Blinding", /*"Fishing",*/ "Flying", "Poison", /*"Puffer",*/ "Tough" ); - public static final MobFamily ENDERMAN = new MobFamily<>( + public static final MobFamily ENDERMAN = new MobFamily<>( FamilyConfig::new, "Enderman", "endermen", 0x161616, new EntityType[] { EntityType.ENDERMAN }, "Blinding", "Icy", "Lightning", "Mini", "Mirage", "Thief" ); - public static final MobFamily WITCH = new MobFamily<>( + public static final MobFamily WITCH = new MobFamily<>( WitchFamilyConfig::new, "Witch", "witches", 0x340000, new EntityType[] { EntityType.WITCH }, "Domination", "Shadows", "Undead", "Wilds", "Wind" ); - public static final MobFamily GHAST = new MobFamily<>( + public static final MobFamily GHAST = new MobFamily<>( GhastFamilyConfig::new, "Ghast", "ghasts", 0xF9F9F9, new EntityType[] { EntityType.GHAST }, "Baby", "Fighter", "King", "Queen", "Unholy", "CorporealShift" ); - public static final MobFamily BLAZE = new MobFamily<>( + public static final MobFamily BLAZE = new MobFamily<>( FamilyConfig::new, "Blaze", "blazes", 0xF6B201, new EntityType[] { EntityType.BLAZE }, "Cinder", "Conflagration", "Ember", "Hellfire", "Inferno", "Jolt", "Wildfire" ); static { - final HashMap, MobFamily> classToFamilyMap = new HashMap<>(); + final HashMap, MobFamily> classToFamilyMap = new HashMap<>(); final ArrayList> allSpecies = new ArrayList<>(); - for( MobFamily family : FAMILY_LIST ) { + for( MobFamily family : FAMILY_LIST ) { for( EntityType replaceable : family.replaceableTypes ) classToFamilyMap.put( replaceable, family ); @@ -126,23 +129,23 @@ public class MobFamily { public static void initBestiary() { } /** @return A list of all families. */ - public static List> getAll() { return Collections.unmodifiableList( FAMILY_LIST ); } + public static List> getAll() { return Collections.unmodifiableList( FAMILY_LIST ); } /** @return A list of all species. */ public static List> getAllSpecies() { return SPECIES_LIST; } /** @return The family of mobs that can replace the passed entity; returns null if the entity is not replaceable. */ @Nullable - public static MobFamily getReplacementFamily( LivingEntity entity ) { + public static MobFamily getReplacementFamily( LivingEntity entity ) { return TYPE_TO_FAMILY_MAP.get( entity.getType() ); } /** The technical name that refers to this family. Note that this is UpperCamelCase, but is often used in lowercase. */ public final String name; - /** The name used to refer to this family in unlocalized situations; e.g. config comments. */ + /** The plural name used to refer to this family in unlocalized situations; e.g. config comments. */ public final String configName; - /** The base egg color for species in this family. Species' eggs differ visually only by spot color. */ + /** The base color for spawn eggs of species in this family. Species' eggs differ visually only by spot color. */ public final int eggBaseColor; /** List of replaceable entity types. The vanilla replacement's entity type is based on the first entry in this array. */ @@ -156,25 +159,31 @@ public class MobFamily { /** Array of all special variant species in this family. In practice, these are the true "special mobs". */ public final Species[] variants; - //public Config.FamilyConfig config; + /** This family's config. */ + public final V config; - private MobFamily( String familyName, String familyKey, int eggColor, EntityType[] replaceable, + private MobFamily( Function, V> configSupplier, + String familyName, String readableName, int eggColor, EntityType[] replaceable, String... variantNames ) { name = familyName; - configName = familyKey; + configName = readableName.toLowerCase( Locale.ROOT ); eggBaseColor = eggColor; replaceableTypes = replaceable; if( replaceable.length < 1 ) throw new IllegalArgumentException( familyName + " family must have at least one replaceable type!" ); - final String packageRoot = References.ENTITY_PACKAGE + name.toLowerCase() + "."; + final String packageRoot = References.ENTITY_PACKAGE + name.toLowerCase(); vanillaReplacement = new Species<>( this, packageRoot, null ); + //noinspection unchecked variants = new Species[variantNames.length]; for( int i = 0; i < variants.length; i++ ) { variants[i] = new Species<>( this, packageRoot, variantNames[i] ); } + config = configSupplier.apply( this ); + config.SPEC.initialize(); + // We register here because otherwise there's no way to find all families FAMILY_LIST.add( this ); } @@ -223,7 +232,7 @@ public class MobFamily { @MethodsReturnNonnullByDefault public static class Species { /** The special mob family this species belongs to. */ - public final MobFamily family; + public final MobFamily family; /** The name of this special variant; or null for vanilla replacement species. */ public final String specialVariantName; /** The technical name that refers to this species. Note that this is UpperCamelCase, but is often used in lowercase. */ @@ -231,7 +240,7 @@ public class MobFamily { /** The entity class for this species. */ public final Class entityClass; - /** The bestiary info describing this species */ + /** The bestiary info describing this species. */ public final BestiaryInfo bestiaryInfo; /** This species's entity type, wrapped in its registry object. */ @@ -239,8 +248,11 @@ public class MobFamily { /** This species's spawn egg item, wrapped in its registry object. */ public final RegistryObject spawnEgg; + /** This species's config. */ + public final SpeciesConfig config; + /** Constructs a new mob species. For vanilla replacements, the variant name is null. */ - private Species( MobFamily parentFamily, String packageRoot, @Nullable String variantName ) { + private Species( MobFamily parentFamily, String packageRoot, @Nullable String variantName ) { final boolean vanillaReplacement = variantName == null; family = parentFamily; @@ -253,14 +265,19 @@ public class MobFamily { // Below require variant class to be defined final EntityType.Builder entityTypeBuilder = makeEntityTypeBuilder( parentFamily.replaceableTypes[0] ); - bestiaryInfo = AnnotationHelper.getBestiaryInfo( this, entityTypeBuilder ); + bestiaryInfo = AnnotationHelper.getBestiaryInfo( this, BestiaryInfo.of( this, entityTypeBuilder ) ).build(); // Initialize deferred registry objects entityType = SMEntities.register( name.toLowerCase( Locale.ROOT ), entityTypeBuilder ); spawnEgg = SMItems.registerSpawnEgg( entityType, parentFamily.eggBaseColor, bestiaryInfo.eggSpotsColor ); + // Config uses bestiary info for default values + config = AnnotationHelper.createConfig( this ); + config.SPEC.initialize(); + // Register this species with the entity class AnnotationHelper.injectSpeciesReference( this ); + AnnotationHelper.verifySpeciesSupplier( this ); } /** Finds the entity class based on a standard format. */ diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/SpecialMob.java b/src/main/java/fathertoast/specialmobs/common/bestiary/SpecialMob.java index 7ca1795..4e29366 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/SpecialMob.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/SpecialMob.java @@ -1,5 +1,7 @@ package fathertoast.specialmobs.common.bestiary; +import fathertoast.specialmobs.common.entity.ISpecialMob; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -14,50 +16,77 @@ import java.lang.annotation.Target; */ @Target( ElementType.TYPE ) public @interface SpecialMob { - /** * REQUIRED. This is injected with a reference to the species during registration so you may access it later, as needed. *

* The annotated field must have a signature that follows the pattern: *

- * public static MobFamily.Species FIELD_NAME; + * {@code public static MobFamily.Species FIELD_NAME;} */ @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.FIELD ) @interface SpeciesReference { } /** - * REQUIRED. This is called during registration to collect static properties of the mob needed for the bestiary - * and for building the species's entity type. - * This is not 'overridable' because all species must have unique info in the bestiary. + * REQUIRED. This is used to enforce overriding {@link ISpecialMob#getSpecies()} in every species entity class. *

* The annotated method must have a signature that follows the pattern: *

- * public static BestiaryInfo METHOD_NAME( EntityType.Builder entityType ) + * {@code public MobFamily.Species getSpecies();} *

- * The returned bestiary info will be used to describe the mob species. - * The builder passed in is a copy of the vanilla 'base' entity type. Common uses of the entity type builder are - * modifying entity size and fire/hazard immunities. + * The returned species should be the field annotated with {@link SpecialMob.SpeciesReference}. + */ + @Retention( RetentionPolicy.RUNTIME ) + @Target( ElementType.METHOD ) + @interface SpeciesSupplier { } + + /** + * REQUIRED. This is called during registration to collect static properties of the mob needed for the bestiary + * and for building the species's entity type. + * This is not 'overridable' because all species must have unique info in the bestiary, however some info in the + * builder is automatically inherited. + *

+ * The annotated method must have a signature that follows the pattern: + *

+ * {@code public static void METHOD_NAME( BestiaryInfo.Builder bestiaryInfo )} + *

+ * The provided bestiary info builder is initialized with as much data from the parent entity as possible. + * The only builder method that absolutely must be called is #color( int ). This will likely later expand to desc. */ @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.METHOD ) @interface BestiaryInfoSupplier { } /** - * OVERRIDABLE. This is called during registration to build the base attributes for the species. - * 'Overridable' static methods inherit from their superclass if not defined in a subclass, but must be defined somewhere. - * This is 'overridable' because not all species need to have different attributes from their parent vanilla mob. + * OPTIONAL-OVERRIDABLE. This is called during registration to generate the species config. + * 'Overridable' static methods inherit from their superclass if not defined in a subclass. + * This is 'overridable' because not all species (or even families) require unique config categories. *

* The annotated method must have a signature that follows the pattern: *

- * public static AttributeModifierMap.MutableAttribute METHOD_NAME() + * {@code public static SpeciesConfig METHOD_NAME( MobFamily.Species species )} + *

+ * The returned config will be loaded immediately after the call and a reference will be stored in the species. + */ + @Retention( RetentionPolicy.RUNTIME ) + @Target( ElementType.METHOD ) + @interface ConfigSupplier { } + + /** + * OVERRIDABLE. This is called during registration to build the base attributes for the species. + * 'Overridable' static methods inherit from their superclass if not defined in a subclass, but must be defined somewhere. + * This is 'overridable' because a few species have a different parent vanilla mob from the rest of their family. + *

+ * The annotated method must have a signature that follows the pattern: + *

+ * {@code public static AttributeModifierMap.MutableAttribute METHOD_NAME()} *

* The returned attribute modifier map builder will be 'built' immediately after the call and registered to be * applied to all entity class instances of the mob species. */ @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.METHOD ) - @interface AttributeCreator { } + @interface AttributeSupplier { } /** * REQUIRED. This is called during data generation to build the mod's default lang files. @@ -65,7 +94,7 @@ public @interface SpecialMob { *

* The annotated method must have a signature that follows the pattern: *

- * public static String[] METHOD_NAME( String langKey ) + * {@code public static String[] METHOD_NAME( String langKey )} *

* The returned string array should be created by References#translations using the given lang key as the first * argument. Always be sure that any non-ASCII characters used are properly handled by the translations method. @@ -83,7 +112,7 @@ public @interface SpecialMob { *

* The annotated method must have a signature that follows the pattern: *

- * public static void METHOD_NAME( LootTableBuilder loot ) + * {@code public static void METHOD_NAME( LootTableBuilder loot )} *

* The builder passed in is a new empty instance and will be 'built' immediately after the call. */ @@ -98,7 +127,7 @@ public @interface SpecialMob { *

* The annotated method must have a signature that follows the pattern: *

- * public static EntityType.IFactory METHOD_NAME() + * {@code public static EntityType.IFactory METHOD_NAME()} */ @Retention( RetentionPolicy.RUNTIME ) @Target( ElementType.METHOD ) diff --git a/src/main/java/fathertoast/specialmobs/common/config/Config.java b/src/main/java/fathertoast/specialmobs/common/config/Config.java index a32e7d1..3e45085 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/Config.java +++ b/src/main/java/fathertoast/specialmobs/common/config/Config.java @@ -35,7 +35,7 @@ public class Config { /** The spec used by this config that defines the file's format. */ public final ToastConfigSpec SPEC; - AbstractConfig( File dir, String fileName, String... fileDescription ) { + public AbstractConfig( File dir, String fileName, String... fileDescription ) { AbstractConfigField.loadingCategory = ""; SPEC = new ToastConfigSpec( dir, fileName ); SPEC.header( TomlHelper.newComment( fileDescription ) ); @@ -50,17 +50,10 @@ public class Config { /** The spec used by this config that defines the file's format. */ protected final ToastConfigSpec SPEC; - AbstractCategory( ToastConfigSpec parent, String name, String... categoryDescription ) { + public AbstractCategory( ToastConfigSpec parent, String name, String... categoryDescription ) { AbstractConfigField.loadingCategory = name + "."; SPEC = parent; SPEC.category( name, TomlHelper.newComment( categoryDescription ) ); } } - - /** The plus or minus symbol (+/-). */ - public static final String PLUS_OR_MINUS = "\u00b1"; - /** The less than or equal to symbol (<=). */ - public static final String LESS_OR_EQUAL = "\u2264"; - /** The greater than or equal to symbol (>=). */ - public static final String GREATER_OR_EQUAL = "\u2265"; } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/MainConfig.java b/src/main/java/fathertoast/specialmobs/common/config/MainConfig.java index 9562310..7f12f7a 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/MainConfig.java +++ b/src/main/java/fathertoast/specialmobs/common/config/MainConfig.java @@ -2,6 +2,7 @@ package fathertoast.specialmobs.common.config; import fathertoast.specialmobs.common.config.field.*; import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; import java.io.File; @@ -12,58 +13,61 @@ public class MainConfig extends Config.AbstractConfig { /** Builds the config spec that should be used for this config. */ MainConfig( File dir, String fileName ) { super( dir, fileName, - "This config contains options that apply to the mod as a whole, including some master disable", - "toggles for convenience." - ); + "This config contains options that apply to the mod as a whole, including some master settings", + "toggles for convenience.", + "", + "Terminology used in Special Mobs configs:", + " * Mob - An entity that is 'alive', short for \"Mobile\" or MobEntity.", + " * Family - The group of mobs based on (but not including) a particular vanilla mob; e.g., Creepers.", + " * Species - A specific type of mob within a family; e.g., Fire Creepers or vanilla-replacement Creepers.", + " * Vanilla Replacement - The one species within a family that is intended to be a replica of the base vanilla mob.", + " * Special Variant - Any species that is not the family's vanilla replacement. Includes species that are", + " replicas of 'vanilla special variants'; i.e. Husks and Strays.", + " * Mob Replacer - The tool that watches vanilla mob spawns and cancels them to spawn this mod's entities." ); GENERAL = new General( SPEC ); } public static class General extends Config.AbstractCategory { - public final IntField updateTime; + public final BooleanField enableMobReplacement; - public final InjectionWrapperField defaultGameRuleNoRegen; + public final BooleanField masterVanillaReplacement; + public final DoubleField masterRandomScaling; - public final BooleanField foodExtraTooltipInfo; - - public final BooleanField disableAbsorptionFeatures; - public final BooleanField disableHealthFeatures; - //public final BooleanField disableHungerFeatures; // NOTE: If/when hunger features are added, also move food configs from health + public final BooleanField enableNausea; + public final BooleanField fancyFishingMobs; General( ToastConfigSpec parent ) { super( parent, "general", - "Options for customizing the mod as a whole." ); + "Options that apply to the Special Mobs mod as a whole.", + "Also includes several 'master toggles' for convenience." ); - updateTime = SPEC.define( new IntField( "update_time", 5, IntField.Range.POSITIVE, - "The number of ticks between this mod's logic/recovery updates (20 ticks = 1 second)." ) ); + enableMobReplacement = SPEC.define( new BooleanField( "enable_mob_replacer", true, + "Whether the Mob Replacer is enabled. This 'hijacks' vanilla mob spawns to use as its own.", + "The Mob Replacer is the traditional spawn method for Special Mobs which allows everything that spawns", + "valid vanilla mobs (e.g. dungeon spawners) to spawn this mod's mobs based on your configs instead." ) ); SPEC.newLine(); - defaultGameRuleNoRegen = SPEC.define( new InjectionWrapperField<>( - new BooleanField( "default_regen_game_rule_disabled", true, - "When set to true, this mod will alter the vanilla regeneration game rule \"naturalRegeneration\" to", - "be \"false\" by default when creating new worlds.", - "Regardless of this config setting, you can still create a world with vanilla health regen ON or OFF", - "by using the Game Rules button on the new world options screen or by using commands in-game." ), - ( wrapped ) -> { - // Note, we are assuming the default is always true without this mod (ie, no other mod changes the default) - //GameRules.GAME_RULE_TYPES.put( GameRules.RULE_NATURAL_REGENERATION, - // GameRules.BooleanValue.create( !wrapped.get() ) ); - } ) ); + masterVanillaReplacement = SPEC.define( new BooleanField( "master_vanilla_replacement", true, + "Whether the mod uses Special Mobs entities in place of vanilla entities for non-special species.", + "This allows your config options to apply to non-special species and allows them to benefit from", + "Special Mob Data and any improvements made to the entity (for example, zombies can use bows & shields).", + "If false, vanilla replacements are disabled for all families; if true, it is determined by the family's config." ) ); + masterRandomScaling = SPEC.define( new DoubleField( "master_random_scaling", 0.07, DoubleField.Range.PERCENT, + "When greater than 0, mobs will have a random render scale applied. This is a visual effect only.", + "For example, with a value of 0.07, mob scale will vary " + ConfigUtil.PLUS_OR_MINUS + "7% of normal size.", + "By default, this applies to all mobs in the mod; but family and species configs can override it." ) ); SPEC.newLine(); - foodExtraTooltipInfo = SPEC.define( new BooleanField( "food.extra_tooltip_info", true, - "Set to true to display nutritional value on the tooltips of food items.", - "Lists hunger and saturation that can be restored from eating. (See health config for healing display.)" ) ); - - SPEC.newLine(); - - disableAbsorptionFeatures = SPEC.define( new BooleanField( "disable_absorption_features", false, - "If set to 'true', disables all features in this mod related to absorption (yellow hearts)." ) ); - disableHealthFeatures = SPEC.define( new BooleanField( "disable_health_features", false, - "If set to 'true', disables all features in this mod related to health (red hearts)." ) ); + enableNausea = SPEC.define( new BooleanField( "enable_nausea_effects", true, + "Set to false to prevent any of this mod's mobs from applying nausea (aka confusion).", + "Use this if the screen warping from nausea hurts your face or makes you sick." ) ); + fancyFishingMobs = SPEC.define( new BooleanField( "fancy_fishing_mobs", true, + "Overrides the default fishing rod item animation so that it is compatible with fishing mobs from this mod.", + "Set to false if it causes problems with another mod. Fishing mobs will instead render a stick while casting." ) ); } } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/CreeperFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/CreeperFamilyConfig.java new file mode 100644 index 0000000..2e4b5f0 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/CreeperFamilyConfig.java @@ -0,0 +1,43 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for creepers. + */ +public class CreeperFamilyConfig extends FamilyConfig { + + public final Creepers CREEPERS; + + /** Builds the config spec that should be used for this config. */ + public CreeperFamilyConfig( MobFamily family ) { + super( family ); + + CREEPERS = new Creepers( SPEC, family ); + } + + public static class Creepers extends Config.AbstractCategory { + + public final DoubleField familyStormChargeChance; + + public final DoubleField superchargeChance; + + Creepers( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + familyStormChargeChance = SPEC.define( new DoubleField( "family_storm_charge_chance", 0.01, DoubleField.Range.PERCENT, + "Chance for " + family.configName + " to spawn charged during thunderstorms.", + "By default, this applies to all " + family.configName + "; but species configs can override it." ) ); + + SPEC.newLine(); + + superchargeChance = SPEC.define( new DoubleField( "supercharge_chance", 0.1, DoubleField.Range.PERCENT, + "Chance for " + family.configName + " to become supercharged when charged in any way." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/FamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/FamilyConfig.java new file mode 100644 index 0000000..94a6389 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/FamilyConfig.java @@ -0,0 +1,87 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.BooleanField; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.file.TomlHelper; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +import java.io.File; +import java.util.List; + +/** + * This is the base config for mob families. This may be extended to add categories specific to the family, but all + * options that are used by all families should be defined in this class. + */ +public class FamilyConfig extends Config.AbstractConfig { + + public static File dir( MobFamily family ) { return new File( Config.CONFIG_DIR, ConfigUtil.noSpaces( family.configName ) ); } + + protected static String fileName( MobFamily family ) { return "_family_of_" + ConfigUtil.noSpaces( family.configName ); } + + /** Category containing all options applicable to mob families as a whole; i.e. not specific to any particular family. */ + public final General GENERAL; + + /** Builds the config spec that should be used for this config. */ + public FamilyConfig( MobFamily family ) { + super( dir( family ), fileName( family ), + "This config contains options that apply to the family of " + family.configName + " as a whole;", + "that is, the vanilla replacement and all special variants." ); + + GENERAL = new General( SPEC, family ); + } + + public static class General extends Config.AbstractCategory { + + public final BooleanField vanillaReplacement; + + public final DoubleField familyRandomScaling; + + public final DoubleField specialVariantChance; + + public final IntField[] specialVariantWeights; + + General( ToastConfigSpec parent, MobFamily family ) { + super( parent, "general", + "Options standard to all mob families (that is, not specific to any particular mob family)." ); + + vanillaReplacement = SPEC.define( new BooleanField( "vanilla_replacement", true, + "Whether this mob family replaces vanilla " + family.configName + " with its vanilla replacement species.", + "The \"master_vanilla_replacement\" setting in the mod's main config must also be true for this to work." ) ); + + SPEC.newLine(); + + familyRandomScaling = SPEC.define( new DoubleField( "family_random_scaling", -1.0, DoubleField.Range.SIGNED_PERCENT, + "When greater than 0, " + family.configName + " will have a random render scale applied. This is a visual effect only.", + "If this is set to a non-negative value, it overrides the value set for \"master_random_scaling\", though", + "species configs can override this value." ) ); + + SPEC.newLine(); + + specialVariantChance = SPEC.define( new DoubleField( "special_variant_chance", 0.25, DoubleField.Range.PERCENT, + "The chance for " + family.configName + " to spawn as special variants." ) ); + // TODO special variant chance exceptions + + SPEC.newLine(); + + List comment; + + // TODO consider wrapping this all up into an 'environment sensitive weighted list' config object? seems handy + comment = TomlHelper.newComment( + "The weight of each " + ConfigUtil.camelCaseToLowerSpace( family.name ) + " species to be chosen as the replacement when", + family.configName + " spawn as special variants. Higher weight is more common." ); + comment.add( TomlHelper.multiFieldInfo( IntField.Range.NON_NEGATIVE ) ); + SPEC.comment( comment ); + specialVariantWeights = new IntField[family.variants.length]; + for( int i = 0; i < specialVariantWeights.length; i++ ) { + specialVariantWeights[i] = SPEC.define( new IntField( + "weight." + ConfigUtil.camelCaseToLowerUnderscore( family.variants[i].specialVariantName ), + family.variants[i].bestiaryInfo.defaultWeight.value, IntField.Range.NON_NEGATIVE, (String[]) null ) ); + } + // TODO special variant weights exceptions + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/GhastFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/GhastFamilyConfig.java new file mode 100644 index 0000000..63d189e --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/GhastFamilyConfig.java @@ -0,0 +1,36 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.BooleanField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for ghasts. + */ +public class GhastFamilyConfig extends FamilyConfig { + + public final Ghasts GHASTS; + + /** Builds the config spec that should be used for this config. */ + public GhastFamilyConfig( MobFamily family ) { + super( family ); + + GHASTS = new Ghasts( SPEC, family ); + } + + public static class Ghasts extends Config.AbstractCategory { + + public final BooleanField allowVerticalTargeting; + + Ghasts( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + allowVerticalTargeting = SPEC.define( new BooleanField( "allow_vertical_targeting", true, + "If true, " + family.configName + " will be allowed to target any visible player in their follow range.", + "As of MC 1.8, vanilla ghasts can only start targeting players nearly completely horizontal from them." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/SilverfishFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/SilverfishFamilyConfig.java new file mode 100644 index 0000000..c824358 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/SilverfishFamilyConfig.java @@ -0,0 +1,36 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for silverfish. + */ +public class SilverfishFamilyConfig extends FamilyConfig { + + public final Silverfish SILVERFISH; + + /** Builds the config spec that should be used for this config. */ + public SilverfishFamilyConfig( MobFamily family ) { + super( family ); + + SILVERFISH = new Silverfish( SPEC, family ); + } + + public static class Silverfish extends Config.AbstractCategory { + + public final DoubleField familyAggressiveChance; + + Silverfish( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + familyAggressiveChance = SPEC.define( new DoubleField( "family_aggressive_chance", 0.05, DoubleField.Range.PERCENT, + "Chance for " + family.configName + " to spawn already calling for reinforcements.", + "By default, this applies to all " + family.configName + "; but species configs can override it." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/SkeletonFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/SkeletonFamilyConfig.java new file mode 100644 index 0000000..a0b2091 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/SkeletonFamilyConfig.java @@ -0,0 +1,36 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for skeletons and wither skeletons. + */ +public class SkeletonFamilyConfig extends FamilyConfig { + + public final Skeletons SKELETONS; + + /** Builds the config spec that should be used for this config. */ + public SkeletonFamilyConfig( MobFamily family ) { + super( family ); + + SKELETONS = new Skeletons( SPEC, family ); + } + + public static class Skeletons extends Config.AbstractCategory { + + public final DoubleField babyChance; + + Skeletons( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + babyChance = SPEC.define( new DoubleField( "baby_chance", 0.05, DoubleField.Range.PERCENT, + "Chance for valid " + family.configName + " to spawn as babies. Baby mobs are about half-sized,", + "move 50% faster, drop 150% more experience, and are 50% cuter." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/SlimeFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/SlimeFamilyConfig.java new file mode 100644 index 0000000..329a56f --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/SlimeFamilyConfig.java @@ -0,0 +1,35 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.BooleanField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for slimes (NOT magma cubes). + */ +public class SlimeFamilyConfig extends FamilyConfig { + + public final Slimes SLIMES; + + /** Builds the config spec that should be used for this config. */ + public SlimeFamilyConfig( MobFamily family ) { + super( family ); + + SLIMES = new Slimes( SPEC, family ); + } + + public static class Slimes extends Config.AbstractCategory { + + public final BooleanField tinySlimesDealDamage; + + Slimes( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + tinySlimesDealDamage = SPEC.define( new BooleanField( "tiny_slimes_deal_damage", true, + "If true, the smallest size " + family.configName + " will be allowed to deal damage (unlike vanilla)." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/family/WitchFamilyConfig.java b/src/main/java/fathertoast/specialmobs/common/config/family/WitchFamilyConfig.java new file mode 100644 index 0000000..dd3bfdd --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/family/WitchFamilyConfig.java @@ -0,0 +1,36 @@ +package fathertoast.specialmobs.common.config.family; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.BooleanField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the family config for witches. + */ +public class WitchFamilyConfig extends FamilyConfig { + + public final Witches WITCHES; + + /** Builds the config spec that should be used for this config. */ + public WitchFamilyConfig( MobFamily family ) { + super( family ); + + WITCHES = new Witches( SPEC, family ); + } + + public static class Witches extends Config.AbstractCategory { + + public final BooleanField useSplashSwiftness; + + Witches( ToastConfigSpec parent, MobFamily family ) { + super( parent, ConfigUtil.noSpaces( family.configName ), + "Options specific to the family of " + family.configName + "." ); + + useSplashSwiftness = SPEC.define( new BooleanField( "use_splash_swiftness", true, + "If true, " + family.configName + " will use splash potions of swiftness when trying to keep up,", + "rather than drinking a swiftness potion. Helps them keep up just a little better than vanilla." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/AttributeListField.java b/src/main/java/fathertoast/specialmobs/common/config/field/AttributeListField.java new file mode 100644 index 0000000..e5655c3 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/field/AttributeListField.java @@ -0,0 +1,146 @@ +package fathertoast.specialmobs.common.config.field; + +import fathertoast.specialmobs.common.config.file.TomlHelper; +import fathertoast.specialmobs.common.config.util.AttributeEntry; +import fathertoast.specialmobs.common.config.util.AttributeList; +import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.AttributeModifierMap; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a config field with an entity list value. + */ +public class AttributeListField extends GenericField { + + /** Provides a detailed description of how to use attribute lists. Recommended to put at the top of any file using attribute lists. */ + public static List verboseDescription() { + List comment = new ArrayList<>(); + comment.add( "Attribute List fields: General format = [ \"namespace:attribute_name operation value\", ... ]" ); + comment.add( " Attribute lists are arrays of base attribute changes. Attributes are defined by their key in the attribute registry," ); + comment.add( " usually following the pattern 'namespace:attribute_name'. The operations that can be performed are +, -, and *. The + and -" ); + comment.add( " operators change the attribute by a flat value by addition/subtraction. The * operator changes the attribute by multiplication." ); + comment.add( " Each entry in the attribute list is applied in the exact order listed." ); + comment.add( " As an example, the entry \"minecraft:generic.max_health + 10.0\" will increase a mob's max health by 10. By convention, never" ); + comment.add( " use the + or - operators for movement speed (minecraft:generic.movement_speed)." ); + return comment; + } + + /** Creates a new field. */ + public AttributeListField( String key, AttributeList defaultValue, String... description ) { + super( key, defaultValue, description ); + } + + /** Applies all attribute changes in this list to the entity attribute builder. */ + public void apply( AttributeModifierMap.MutableAttribute builder ) { get().apply( builder ); } + + /** Applies all attribute changes in this list to the entity. */ + public void apply( LivingEntity entity ) { get().apply( entity ); } + + /** Adds info about the field type, format, and bounds to the end of a field's description. */ + public void appendFieldInfo( List comment ) { + comment.add( TomlHelper.fieldInfoFormat( "Attribute List", valueDefault, + "[ \"namespace:attribute_name operation value\", ... ]" ) ); + comment.add( " Range for Values: " + TomlHelper.fieldRange( DoubleField.Range.ANY.MIN, DoubleField.Range.ANY.MAX ) ); + } + + /** + * Loads this field's value from the given raw toml value. If anything goes wrong, correct it at the lowest level possible. + *

+ * For example, a missing value should be set to the default, while an out-of-range value should be adjusted to the + * nearest in-range value + */ + @Override + public void load( @Nullable Object raw ) { + if( raw == null ) { + value = valueDefault; + return; + } + List list = TomlHelper.parseStringList( raw ); + List entryList = new ArrayList<>(); + for( String line : list ) { + AttributeEntry entry = parseEntry( line ); + if( entry != null ) { + entryList.add( entry ); + } + } + value = new AttributeList( entryList ); + } + + /** Parses a single entry line and returns a valid result if possible, or null if the entry is completely invalid. */ + @Nullable + private AttributeEntry parseEntry( final String line ) { + // Parse the attribute-operation-value array + final String[] args = line.split( " ", 4 ); + if( args.length > 3 ) { + SpecialMobs.LOG.warn( "Entry has for {} \"{}\" is too long! Deleting excess. Invalid entry: {}", + getClass(), getKey(), line ); + } + + final Attribute attribute; + final ResourceLocation regKey = new ResourceLocation( args[0].trim() ); + if( !ForgeRegistries.ATTRIBUTES.containsKey( regKey ) ) { + SpecialMobs.LOG.warn( "Invalid entry for {} \"{}\"! Deleting entry. Invalid entry: {}", + getClass(), getKey(), line ); // TODO note: I don't know if attributes will be registered at this point + return null; + } + attribute = ForgeRegistries.ATTRIBUTES.getValue( regKey ); + + final int operator; + if( args.length < 2 ) { + SpecialMobs.LOG.warn( "Entry has no operator for {} \"{}\"! Replacing missing operator with +. Invalid entry: {}", + getClass(), getKey(), line ); + operator = 1; + } + else { + switch( args[1] ) { + case "*": operator = 0; + break; + case "+": operator = 1; + break; + case "-": operator = -1; + break; + default: operator = 1; + SpecialMobs.LOG.warn( "Entry has invalid operator {} for {} \"{}\"! Replacing operator with +. " + + "Invalid entry: {}", args[1], getClass(), getKey(), line ); + break; + } + } + final int identityValue = operator == 0 ? 1 : 0; + + final double value; + if( args.length < 3 ) { + SpecialMobs.LOG.warn( "Entry has no value for {} \"{}\"! Replacing missing value with {}. Invalid entry: {}", + getClass(), getKey(), identityValue, line ); + value = identityValue; + } + else { + value = parseValue( args[2], line, identityValue ); + } + + //noinspection ConstantConditions + return operator == 0 ? AttributeEntry.mult( attribute, value ) : AttributeEntry.add( attribute, value * operator ); + } + + /** Parses a single value argument and returns a valid result. */ + private double parseValue( final String arg, final String line, final int identity ) { + // Try to parse the value + double value; + try { + value = Double.parseDouble( arg ); + } + catch( NumberFormatException ex ) { + // This is thrown if the string is not a parsable number + SpecialMobs.LOG.warn( "Invalid value for {} \"{}\"! Falling back to {}. Invalid entry: {}", + getClass(), getKey(), identity, line ); + value = identity; + } + return value; + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/BlockListField.java b/src/main/java/fathertoast/specialmobs/common/config/field/BlockListField.java index cedcbd7..fc0ae85 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/field/BlockListField.java +++ b/src/main/java/fathertoast/specialmobs/common/config/field/BlockListField.java @@ -14,9 +14,8 @@ import java.util.List; @SuppressWarnings( "unused" ) public class BlockListField extends GenericField { - /** Provides a detailed description of how to use entity lists. Recommended putting at the top of any file using entity lists. */ - @Override - public List verboseDescription() { + /** Provides a detailed description of how to use block lists. Recommended putting at the top of any file using block lists. */ + public static List verboseDescription() { List comment = new ArrayList<>(); comment.add( "Block List fields: General format = [ \"namespace:block_name[property1=value1,...]\", ... ]" ); comment.add( " Block lists are arrays of blocks and partial block states." ); diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/DoubleField.java b/src/main/java/fathertoast/specialmobs/common/config/field/DoubleField.java index c6cd33b..ccfb252 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/field/DoubleField.java +++ b/src/main/java/fathertoast/specialmobs/common/config/field/DoubleField.java @@ -103,6 +103,8 @@ public class DoubleField extends AbstractConfigField { NON_NEGATIVE( 0.0, Double.POSITIVE_INFINITY ), /** Accepts any value between 0 and 1. */ PERCENT( 0.0, 1.0 ), + /** Accepts any value between -1 and 1. */ + SIGNED_PERCENT( -1.0, 1.0 ), /** Accepts any value between -1 and 2. */ DROP_CHANCE( -1.0, 2.0 ); diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/EntityListField.java b/src/main/java/fathertoast/specialmobs/common/config/field/EntityListField.java index 9c08074..1604190 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/field/EntityListField.java +++ b/src/main/java/fathertoast/specialmobs/common/config/field/EntityListField.java @@ -22,8 +22,7 @@ public class EntityListField extends GenericField { public static final String REG_KEY_DEFAULT = "default"; /** Provides a detailed description of how to use entity lists. Recommended to put at the top of any file using entity lists. */ - @Override - public List verboseDescription() { + public static List verboseDescription() { List comment = new ArrayList<>(); comment.add( "Entity List fields: General format = [ \"namespace:entity_type value1 value2 ...\", ... ]" ); comment.add( " Entity lists are arrays of entity types. Some entity lists specify a number of values linked to each entity type." ); diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/GenericField.java b/src/main/java/fathertoast/specialmobs/common/config/field/GenericField.java index 9994e1d..bc4305e 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/field/GenericField.java +++ b/src/main/java/fathertoast/specialmobs/common/config/field/GenericField.java @@ -1,8 +1,5 @@ package fathertoast.specialmobs.common.config.field; -import javax.annotation.Nullable; -import java.util.List; - /** * Represents a config field with an object value. *

@@ -23,11 +20,6 @@ public abstract class GenericField extends AbstractConfigField { super( key, description ); valueDefault = defaultValue; } - - @Nullable - public List verboseDescription() { - return null; - } /** @return Returns the config field's value. */ public T get() { return value; } diff --git a/src/main/java/fathertoast/specialmobs/common/config/field/RegistryEntryListField.java b/src/main/java/fathertoast/specialmobs/common/config/field/RegistryEntryListField.java new file mode 100644 index 0000000..8de3ed0 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/field/RegistryEntryListField.java @@ -0,0 +1,57 @@ +package fathertoast.specialmobs.common.config.field; + +import fathertoast.specialmobs.common.config.file.TomlHelper; +import fathertoast.specialmobs.common.config.util.RegistryEntryList; +import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a config field with a registry entry list value. + *

+ * See also: {@link net.minecraftforge.registries.ForgeRegistries} + */ +@SuppressWarnings( "unused" ) +public class RegistryEntryListField> extends GenericField> { + + /** Provides a detailed description of how to use registry entry lists. Recommended putting at the top of any file using registry entry lists. */ + public static List verboseDescription() { + List comment = new ArrayList<>(); + comment.add( "Registry Entry List fields: General format = [ \"namespace:entry_name\", ... ]" ); + comment.add( " Registry entry lists are arrays of registry keys. Many things in the game, such as blocks or potions, are defined" ); + comment.add( " by their registry key within a registry. For example, all items are registered in the \"minecraft:item\" registry." ); + comment.add( " An asterisk '*' can be used to match multiple registry keys. For example, 'minecraft:*' will match all vanilla entries" ); + comment.add( " within the registry entry list's target registry." ); + return comment; + } + + /** Creates a new field. */ + public RegistryEntryListField( String key, RegistryEntryList defaultValue, String... description ) { + super( key, defaultValue, description ); + } + + /** Adds info about the field type, format, and bounds to the end of a field's description. */ + public void appendFieldInfo( List comment ) { + comment.add( TomlHelper.fieldInfoFormat( "\"" + SpecialMobs.toString( valueDefault.getRegistry().getRegistryName() ) + + "\" Registry List", valueDefault, "[ \"namespace:entry_name\", ... ]" ) ); + } + + /** + * Loads this field's value from the given raw toml value. If anything goes wrong, correct it at the lowest level possible. + *

+ * For example, a missing value should be set to the default, while an out-of-range value should be adjusted to the + * nearest in-range value + */ + @Override + public void load( @Nullable Object raw ) { + if( raw == null ) { + value = valueDefault; + return; + } + // All the actual loading is done through the objects + value = new RegistryEntryList<>( this, valueDefault.getRegistry(), TomlHelper.parseStringList( raw ) ); + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/file/ToastConfigSpec.java b/src/main/java/fathertoast/specialmobs/common/config/file/ToastConfigSpec.java index bc80ecb..423e923 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/file/ToastConfigSpec.java +++ b/src/main/java/fathertoast/specialmobs/common/config/file/ToastConfigSpec.java @@ -6,8 +6,7 @@ import com.electronwill.nightconfig.core.file.FileWatcher; import com.electronwill.nightconfig.core.io.CharacterOutput; import com.electronwill.nightconfig.core.io.ParsingException; import com.electronwill.nightconfig.core.io.WritingException; -import fathertoast.specialmobs.common.config.field.AbstractConfigField; -import fathertoast.specialmobs.common.config.field.GenericField; +import fathertoast.specialmobs.common.config.field.*; import fathertoast.specialmobs.common.core.SpecialMobs; import java.io.File; @@ -338,13 +337,17 @@ public class ToastConfigSpec { /** @param comment The file comment to insert. */ public void header( List comment ) { ACTIONS.add( new Header( this, comment ) ); } - /** Inserts a detailed description of how to use the given field. */ - public void verboseFieldDesc( GenericField field ) { - final List description = field.verboseDescription(); - - if( description != null && !description.isEmpty() ) - ACTIONS.add( new Comment( field.verboseDescription() ) ); - } + /** Inserts a detailed description of how to use the registry entry list field. */ + public void describeRegistryEntryList() { ACTIONS.add( new Comment( RegistryEntryListField.verboseDescription() ) ); } + + /** Inserts a detailed description of how to use the entity list field. */ + public void describeEntityList() { ACTIONS.add( new Comment( EntityListField.verboseDescription() ) ); } + + /** Inserts a detailed description of how to use the attribute list field. */ + public void describeAttributeList() { ACTIONS.add( new Comment( AttributeListField.verboseDescription() ) ); } + + /** Inserts a detailed description of how to use the block list field. */ + public void describeBlockList() { ACTIONS.add( new Comment( BlockListField.verboseDescription() ) ); } /** * @param name The category name. diff --git a/src/main/java/fathertoast/specialmobs/common/config/file/TomlHelper.java b/src/main/java/fathertoast/specialmobs/common/config/file/TomlHelper.java index acf5d08..c4017e8 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/file/TomlHelper.java +++ b/src/main/java/fathertoast/specialmobs/common/config/file/TomlHelper.java @@ -2,16 +2,16 @@ package fathertoast.specialmobs.common.config.file; import com.electronwill.nightconfig.core.NullObject; import com.electronwill.nightconfig.core.utils.StringUtils; -import fathertoast.specialmobs.common.config.Config; import fathertoast.specialmobs.common.config.field.DoubleField; import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.util.ConfigUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public final class TomlHelper { - private TomlHelper() {} // This is a static access only class that cannot be instantiated + private TomlHelper() { } // This is a static access only class that cannot be instantiated /** Attempts to convert a toml literal to a string list. May or may not be accurate. */ public static List parseStringList( Object value ) { @@ -184,10 +184,10 @@ public final class TomlHelper { private static String fieldRangeNoLimit() { return "Any Value"; } /** @return A range representation of toml literals with only an upper limit. */ - private static String fieldRangeUpperLimit( Number max ) { return Config.LESS_OR_EQUAL + " " + toLiteral( max ); } + private static String fieldRangeUpperLimit( Number max ) { return ConfigUtil.LESS_OR_EQUAL + " " + toLiteral( max ); } /** @return A range representation of toml literals with only a lower limit. */ - private static String fieldRangeLowerLimit( Number min ) { return Config.GREATER_OR_EQUAL + " " + toLiteral( min ); } + private static String fieldRangeLowerLimit( Number min ) { return ConfigUtil.GREATER_OR_EQUAL + " " + toLiteral( min ); } /** @return A range representation of toml literals with both a lower and upper limit. */ private static String fieldRangeInterval( Number min, Number max ) { return toLiteral( min ) + " ~ " + toLiteral( max ); } diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/BlazeSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/BlazeSpeciesConfig.java new file mode 100644 index 0000000..6fb1adb --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/BlazeSpeciesConfig.java @@ -0,0 +1,38 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for blazes. + */ +public class BlazeSpeciesConfig extends SpeciesConfig { + + public final Blazes BLAZES; + + /** Builds the config spec that should be used for this config. */ + public BlazeSpeciesConfig( MobFamily.Species species, int fireballBurstCount, int fireballBurstDelay ) { + super( species ); + + BLAZES = new Blazes( SPEC, species, speciesName, fireballBurstCount, fireballBurstDelay ); + } + + public static class Blazes extends Config.AbstractCategory { + + public final IntField fireballBurstCount; + public final IntField fireballBurstDelay; + + Blazes( ToastConfigSpec parent, MobFamily.Species species, String speciesName, int burstCount, int burstDelay ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + fireballBurstCount = SPEC.define( new IntField( "fireball_attack.burst_count", burstCount, IntField.Range.NON_NEGATIVE, + "The number of fireballs " + speciesName + " launch with each burst." ) ); + fireballBurstDelay = SPEC.define( new IntField( "fireball_attack.burst_delay", burstDelay, IntField.Range.NON_NEGATIVE, + "The time (in ticks) " + speciesName + " wait between each fireball in a burst. (20 ticks = 1 second)" ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/CreeperSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/CreeperSpeciesConfig.java new file mode 100644 index 0000000..4f247a3 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/CreeperSpeciesConfig.java @@ -0,0 +1,54 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.BooleanField; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for creepers. + */ +public class CreeperSpeciesConfig extends SpeciesConfig { + + public final Creepers CREEPERS; + + /** Builds the config spec that should be used for this config. */ + public CreeperSpeciesConfig( MobFamily.Species species, + boolean cannotExplodeWhileWet, boolean explodeWhileBurning, boolean explodeWhenShot ) { + super( species ); + + CREEPERS = new Creepers( SPEC, species, speciesName, cannotExplodeWhileWet, explodeWhileBurning, explodeWhenShot ); + } + + public static class Creepers extends Config.AbstractCategory { + + public final DoubleField stormChargeChance; + + /** Note that this is inverted from how it is normally seen and used elsewhere. This is to avoid double-negatives in the config. */ + public final BooleanField canExplodeWhileWet; + public final BooleanField explodesWhileBurning; + public final BooleanField explodesWhenShot; + + Creepers( ToastConfigSpec parent, MobFamily.Species species, String speciesName, + boolean cannotExplodeWhileWet, boolean explodeWhileBurning, boolean explodeWhenShot ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + stormChargeChance = SPEC.define( new DoubleField( "storm_charge_chance", -1.0, DoubleField.Range.SIGNED_PERCENT, + "Chance for " + speciesName + " to spawn charged during thunderstorms.", + "If this is set to a non-negative value, it overrides the value set for \"family_storm_charge_chance\"." ) ); + + SPEC.newLine(); + + canExplodeWhileWet = SPEC.define( new BooleanField( "can_explode_while_wet", !cannotExplodeWhileWet, + "If true, " + speciesName + " can explode while wet (normal creeper behavior)." ) ); + explodesWhileBurning = SPEC.define( new BooleanField( "explodes_while_burning", explodeWhileBurning, + "If true, " + speciesName + " will explode while burning. If extinguished before the fuse runs", + "out, they will resume normal behavior." ) ); + explodesWhenShot = SPEC.define( new BooleanField( "explodes_when_shot", explodeWhenShot, + "If true, " + speciesName + " will explode when hit by an indirect attack (e.g. an arrow)." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/MotherSpiderSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/MotherSpiderSpeciesConfig.java new file mode 100644 index 0000000..bd74a12 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/MotherSpiderSpeciesConfig.java @@ -0,0 +1,49 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class MotherSpiderSpeciesConfig extends SpiderSpeciesConfig { + + public final Mother MOTHER; + + /** Builds the config spec that should be used for this config. */ + public MotherSpiderSpeciesConfig( MobFamily.Species species, double spitChance, + int minBabies, int maxBabies, int minExtraBabies, int maxExtraBabies ) { + super( species, spitChance ); + + MOTHER = new Mother( SPEC, species, speciesName, minBabies, maxBabies, minExtraBabies, maxExtraBabies ); + } + + public static class Mother extends Config.AbstractCategory { + + public final IntField.RandomRange babies; + + public final IntField.RandomRange extraBabies; + + Mother( ToastConfigSpec parent, MobFamily.Species species, String speciesName, + int minBabies, int maxBabies, int minExtraBabies, int maxExtraBabies ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + babies = new IntField.RandomRange( + SPEC.define( new IntField( "babies.min", minBabies, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of babies " + speciesName + " spawn on death.", + "Any remaining 'extra babies' will added to the amount spawned on death (see below)." ) ), + SPEC.define( new IntField( "babies.max", maxBabies, IntField.Range.NON_NEGATIVE ) ) + ); + + SPEC.newLine(); + + extraBabies = new IntField.RandomRange( + SPEC.define( new IntField( "extra_babies.min", minExtraBabies, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of babies that " + speciesName + " can spawn from hits before death.", + "Any remaining 'extra babies' will added to the amount spawned on death (see above)." ) ), + SPEC.define( new IntField( "extra_babies.max", maxExtraBabies, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/QueenGhastSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/QueenGhastSpeciesConfig.java new file mode 100644 index 0000000..0450a82 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/QueenGhastSpeciesConfig.java @@ -0,0 +1,46 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class QueenGhastSpeciesConfig extends SpeciesConfig { + + public final Queen QUEEN; + + /** Builds the config spec that should be used for this config. */ + public QueenGhastSpeciesConfig( MobFamily.Species species, int minBabies, int maxBabies, int minSummons, int maxSummons ) { + super( species ); + + QUEEN = new Queen( SPEC, species, speciesName, minBabies, maxBabies, minSummons, maxSummons ); + } + + public static class Queen extends Config.AbstractCategory { + + public final IntField.RandomRange babies; + + public final IntField.RandomRange summons; + + Queen( ToastConfigSpec parent, MobFamily.Species species, String speciesName, + int minBabies, int maxBabies, int minSummons, int maxSummons ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + babies = new IntField.RandomRange( + SPEC.define( new IntField( "babies.min", minBabies, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of babies " + speciesName + " spawn on death." ) ), + SPEC.define( new IntField( "babies.max", maxBabies, IntField.Range.NON_NEGATIVE ) ) + ); + + SPEC.newLine(); + + summons = new IntField.RandomRange( + SPEC.define( new IntField( "summons.min", minSummons, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of times " + speciesName + " can summon minions." ) ), + SPEC.define( new IntField( "summons.max", maxSummons, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/SilverfishSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/SilverfishSpeciesConfig.java new file mode 100644 index 0000000..c0a8a5c --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/SilverfishSpeciesConfig.java @@ -0,0 +1,45 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for silverfish. + */ +public class SilverfishSpeciesConfig extends SpeciesConfig { + + public final Silverfish SILVERFISH; + + /** Builds the config spec that should be used for this config. */ + public SilverfishSpeciesConfig( MobFamily.Species species, double spitChance ) { + super( species ); + + SILVERFISH = new Silverfish( SPEC, species, speciesName, spitChance ); + } + + public static class Silverfish extends Config.AbstractCategory { + + public final DoubleField aggressiveChance; + + public final DoubleField spitterChance; + + Silverfish( ToastConfigSpec parent, MobFamily.Species species, String speciesName, double spitChance ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + aggressiveChance = SPEC.define( new DoubleField( "aggressive_chance", -1.0, DoubleField.Range.SIGNED_PERCENT, + "Chance for " + speciesName + " to spawn already calling for reinforcements.", + "If this is set to a non-negative value, it overrides the value set for \"family_aggressive_chance\"." ) ); + + SPEC.newLine(); + + // Automatically set the default spitter chance to 0% if the mob has ranged attacks disabled by default + final double effectiveDefault = species.bestiaryInfo.rangedAttackMaxRange > 0.0F ? spitChance : 0.0; + spitterChance = SPEC.define( new DoubleField( "spitter_chance", effectiveDefault, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn as a 'spitter', which enables their ranged attack (if max range > 0)." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/SkeletonSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/SkeletonSpeciesConfig.java new file mode 100644 index 0000000..7073d11 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/SkeletonSpeciesConfig.java @@ -0,0 +1,45 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for skeletons and wither skeletons. + */ +public class SkeletonSpeciesConfig extends SpeciesConfig { + + public final Skeletons SKELETONS; + + /** Builds the config spec that should be used for this config. */ + public SkeletonSpeciesConfig( MobFamily.Species species, double bowChance, double shieldChance ) { + super( species ); + + SKELETONS = new Skeletons( SPEC, species, speciesName, bowChance, shieldChance ); + } + + public static class Skeletons extends Config.AbstractCategory { + + public final DoubleField bowEquipChance; + + public final DoubleField shieldEquipChance; + + Skeletons( ToastConfigSpec parent, MobFamily.Species species, String speciesName, double bowChance, double shieldChance ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + // Automatically set the default bow chance to 0% if the mob has ranged attacks disabled by default + final double effectiveDefault = species.bestiaryInfo.rangedAttackMaxRange > 0.0F ? bowChance : 0.0; + bowEquipChance = SPEC.define( new DoubleField( "bow_chance", effectiveDefault, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn with a bow, which enables their ranged attack (if max range > 0)." ) ); + + SPEC.newLine(); + + shieldEquipChance = SPEC.define( new DoubleField( "shield_chance", shieldChance, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn with a shield if they did not spawn with a bow.", + "Shield users have a 33% chance to block frontal attacks (100% vs. long range attacks) and can be broken by axes." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/SpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/SpeciesConfig.java new file mode 100644 index 0000000..163b272 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/SpeciesConfig.java @@ -0,0 +1,143 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.family.FamilyConfig; +import fathertoast.specialmobs.common.config.field.*; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; +import net.minecraft.block.Block; +import net.minecraft.potion.Effect; + +/** + * This is the base config for mob species. This may be extended to add categories specific to the species, but all + * options that are used by all species should be defined in this class. + */ +public class SpeciesConfig extends Config.AbstractConfig { + + public static final String SPECIAL_DATA_SUBCAT = "special_data."; + + protected static String fileName( MobFamily.Species species ) { + return (species.specialVariantName == null ? "_normal" : ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName )) + + "_" + ConfigUtil.noSpaces( species.family.configName ); + } + + protected static String variantName( MobFamily.Species species ) { + return species.specialVariantName == null ? "vanilla replacement" : ConfigUtil.camelCaseToLowerSpace( species.specialVariantName ); + } + + /** The full readable name for the species in lower space case; e.g., "baby cave spiders". */ + protected final String speciesName; + + /** Category containing all options applicable to mob species as a whole; i.e. not specific to any particular species. */ + public final General GENERAL; + + /** Builds the config spec that should be used for this config. */ + public SpeciesConfig( MobFamily.Species species ) { + super( FamilyConfig.dir( species.family ), fileName( species ), + String.format( "This config contains options that apply only to the %s %s species.", + species.specialVariantName, ConfigUtil.camelCaseToLowerSpace( species.family.name ) ) ); + SPEC.newLine(); + SPEC.describeAttributeList(); + SPEC.describeRegistryEntryList(); + + speciesName = variantName( species ) + " " + species.family.configName; + + GENERAL = new General( SPEC, species, speciesName ); + } + + public static class General extends Config.AbstractCategory { + + public final DoubleField randomScaling; + + public final AttributeListField attributeChanges; + + public final IntField experience; + public final IntField healTime; + public final DoubleField fallDamageMultiplier; + public final BooleanField isImmuneToFire; + public final BooleanField isImmuneToBurning; + public final BooleanField canBreatheInWater; + public final BooleanField ignoreWaterPush; + public final BooleanField isDamagedByWater; + public final BooleanField allowLeashing; + public final BooleanField ignorePressurePlates; + public final RegistryEntryListField immuneToStickyBlocks; + public final RegistryEntryListField immuneToPotions; + + // These are at the end because they may or may not be present (not applicable for all families) + public final DoubleField rangedAttackDamage; + public final DoubleField rangedAttackSpread; + public final DoubleField rangedWalkSpeed; + public final IntField rangedAttackCooldown; + public final IntField rangedAttackMaxCooldown; + public final DoubleField rangedAttackMaxRange; + + General( ToastConfigSpec parent, MobFamily.Species species, String speciesName ) { + super( parent, "general", + "Options standard to all mob species (that is, not specific to any particular mob species)." ); + final BestiaryInfo info = species.bestiaryInfo; + + randomScaling = SPEC.define( new DoubleField( "random_scaling", -1.0, DoubleField.Range.SIGNED_PERCENT, + "When greater than 0, " + speciesName + " will have a random render scale applied. This is a visual effect only.", + "If this is set to a non-negative value, it overrides the value set for both \"master_random_scaling\" and", + "\"family_random_scaling\". The priority is species value > family value > master value." ) ); + + SPEC.newLine(); + + attributeChanges = SPEC.define( new AttributeListField( "attributes", info.defaultAttributes, + "Attribute modifiers for " + speciesName + ". If no attribute changes are defined here, " + speciesName, + "will have the exact same attributes as their parent vanilla mob." ) ); + + SPEC.newLine(); + + experience = SPEC.define( new IntField( SPECIAL_DATA_SUBCAT + "experience", info.experience, IntField.Range.NON_NEGATIVE, + "The amount of experience " + speciesName + " drop when killed by a player. Multiplied by 2.5 for babies.", + "Extra experience may drop based on equipment. Slime-style mobs also drop experience equal to slime size." ) ); + healTime = SPEC.define( new IntField( SPECIAL_DATA_SUBCAT + "heal_time", info.healTime, IntField.Range.NON_NEGATIVE, + "If greater than 0, " + speciesName + " will heal 1 half-heart of health every \"heal_time\" ticks. (20 ticks = 1 second)" ) ); + fallDamageMultiplier = SPEC.define( new DoubleField( SPECIAL_DATA_SUBCAT + "fall_damage_multiplier", info.fallDamageMultiplier, DoubleField.Range.NON_NEGATIVE, + "Fall damage taken by " + speciesName + " is multiplied by this value. 0 is fall damage immunity." ) ); + isImmuneToFire = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "immune_to_fire", info.isImmuneToFire, + "If true, " + speciesName + " will take no fire damage. Does not affect spawn restrictions." ) ); + isImmuneToBurning = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "immune_to_burning", info.isImmuneToBurning, + "If true, " + speciesName + " cannot be set on fire (this setting only matters if not immune to fire)." ) ); + canBreatheInWater = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "immune_to_drowning", info.canBreatheInWater, + "If true, " + speciesName + " can breathe in water." ) ); + ignoreWaterPush = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "immune_to_fluid_push", info.ignoreWaterPush, + "If true, " + speciesName + " will ignore forces applied by flowing fluids." ) ); + isDamagedByWater = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "sensitive_to_water", info.isDamagedByWater, + "If true, " + speciesName + " will be continuously damaged while wet." ) ); + allowLeashing = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "allow_leashing", info.allowLeashing, + "If true, " + speciesName + " can be leashed. (Note: Leashed mobs can still attack you.)" ) ); + ignorePressurePlates = SPEC.define( new BooleanField( SPECIAL_DATA_SUBCAT + "immune_to_pressure_plates", info.ignorePressurePlates, + "If true, " + speciesName + " will not trigger pressure plates." ) ); + immuneToStickyBlocks = SPEC.define( new RegistryEntryListField<>( SPECIAL_DATA_SUBCAT + "immune_to_sticky_blocks", info.immuneToStickyBlocks, + ConfigUtil.properCase( speciesName ) + " will not be 'trapped' in any blocks specified here (e.g. \"cobweb\" or \"sweet_berry_bush\")." ) ); + immuneToPotions = SPEC.define( new RegistryEntryListField<>( SPECIAL_DATA_SUBCAT + "immune_to_effects", info.immuneToPotions, + ConfigUtil.properCase( speciesName ) + " cannot be inflicted with any effects specified here (e.g. \"instant_damage\" or \"regeneration\")." ) ); + + SPEC.newLine(); + + rangedAttackDamage = info.rangedAttackDamage < 0.0F ? null : + SPEC.define( new DoubleField( SPECIAL_DATA_SUBCAT + "ranged_attack.damage", info.rangedAttackDamage, DoubleField.Range.NON_NEGATIVE, + "" ) ); + rangedAttackSpread = info.rangedAttackSpread < 0.0F ? null : + SPEC.define( new DoubleField( SPECIAL_DATA_SUBCAT + "ranged_attack.spread", info.rangedAttackSpread, DoubleField.Range.NON_NEGATIVE, + "." ) ); + rangedWalkSpeed = info.rangedWalkSpeed < 0.0F ? null : + SPEC.define( new DoubleField( SPECIAL_DATA_SUBCAT + "ranged_attack.walk_speed", info.rangedWalkSpeed, DoubleField.Range.NON_NEGATIVE, + "." ) ); + rangedAttackCooldown = info.rangedAttackCooldown < 0 ? null : + SPEC.define( new IntField( SPECIAL_DATA_SUBCAT + "ranged_attack.charge_time", info.rangedAttackCooldown, IntField.Range.NON_NEGATIVE, + "The delay (in ticks) to 'charge up' and perform a ranged attack. (20 ticks = 1 second)" ) ); + rangedAttackMaxCooldown = info.rangedAttackMaxCooldown < 0 ? null : + SPEC.define( new IntField( SPECIAL_DATA_SUBCAT + "ranged_attack.refire_time", info.rangedAttackMaxCooldown, IntField.Range.NON_NEGATIVE, + "The total delay (in ticks) between each ranged attack. (20 ticks = 1 second)" ) ); + rangedAttackMaxRange = info.rangedAttackMaxRange < 0.0F ? null : + SPEC.define( new DoubleField( SPECIAL_DATA_SUBCAT + "ranged_attack.max_range", info.rangedAttackMaxRange, DoubleField.Range.NON_NEGATIVE, + "" ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/SpiderSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/SpiderSpeciesConfig.java new file mode 100644 index 0000000..be69e97 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/SpiderSpeciesConfig.java @@ -0,0 +1,37 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for spiders and cave spiders. + */ +public class SpiderSpeciesConfig extends SpeciesConfig { + + public final Spiders SPIDERS; + + /** Builds the config spec that should be used for this config. */ + public SpiderSpeciesConfig( MobFamily.Species species, double spitChance ) { + super( species ); + + SPIDERS = new Spiders( SPEC, species, speciesName, spitChance ); + } + + public static class Spiders extends Config.AbstractCategory { + + public final DoubleField spitterChance; + + Spiders( ToastConfigSpec parent, MobFamily.Species species, String speciesName, double spitChance ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + // Automatically set the default spitter chance to 0% if the mob has ranged attacks disabled by default + final double effectiveDefault = species.bestiaryInfo.rangedAttackMaxRange > 0.0F ? spitChance : 0.0; + spitterChance = SPEC.define( new DoubleField( "spitter_chance", effectiveDefault, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn as a 'spitter', which enables their ranged attack (if max range > 0)." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/SplittingCreeperSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/SplittingCreeperSpeciesConfig.java new file mode 100644 index 0000000..ba6485d --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/SplittingCreeperSpeciesConfig.java @@ -0,0 +1,38 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class SplittingCreeperSpeciesConfig extends CreeperSpeciesConfig { + + public final Splitting SPLITTING; + + /** Builds the config spec that should be used for this config. */ + public SplittingCreeperSpeciesConfig( MobFamily.Species species, + boolean cannotExplodeWhileWet, boolean explodeWhileBurning, boolean explodeWhenShot, + int minExtraBabies, int maxExtraBabies ) { + super( species, cannotExplodeWhileWet, explodeWhileBurning, explodeWhenShot ); + + SPLITTING = new Splitting( SPEC, species, speciesName, minExtraBabies, maxExtraBabies ); + } + + public static class Splitting extends Config.AbstractCategory { + + public final IntField.RandomRange extraBabies; + + Splitting( ToastConfigSpec parent, MobFamily.Species species, String speciesName, int minExtraBabies, int maxExtraBabies ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + extraBabies = new IntField.RandomRange( + SPEC.define( new IntField( "extra_babies.min", minExtraBabies, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of extra babies that " + speciesName + " spawn with their explosion.", + "This is in addition to the number spawned based on explosion power." ) ), + SPEC.define( new IntField( "extra_babies.max", maxExtraBabies, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/UndeadWitchSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/UndeadWitchSpeciesConfig.java new file mode 100644 index 0000000..e01521c --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/UndeadWitchSpeciesConfig.java @@ -0,0 +1,35 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class UndeadWitchSpeciesConfig extends SpeciesConfig { + + public final Undead UNDEAD; + + /** Builds the config spec that should be used for this config. */ + public UndeadWitchSpeciesConfig( MobFamily.Species species, int minSummons, int maxSummons ) { + super( species ); + + UNDEAD = new Undead( SPEC, species, speciesName, minSummons, maxSummons ); + } + + public static class Undead extends Config.AbstractCategory { + + public final IntField.RandomRange summons; + + Undead( ToastConfigSpec parent, MobFamily.Species species, String speciesName, int minSummons, int maxSummons ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + summons = new IntField.RandomRange( + SPEC.define( new IntField( "summons.min", minSummons, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of times " + speciesName + " can summon minions." ) ), + SPEC.define( new IntField( "summons.max", maxSummons, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/WebSpiderSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/WebSpiderSpeciesConfig.java new file mode 100644 index 0000000..6f733cf --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/WebSpiderSpeciesConfig.java @@ -0,0 +1,35 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class WebSpiderSpeciesConfig extends SpiderSpeciesConfig { + + public final Web WEB; + + /** Builds the config spec that should be used for this config. */ + public WebSpiderSpeciesConfig( MobFamily.Species species, double spitChance, int minWebs, int maxWebs ) { + super( species, spitChance ); + + WEB = new Web( SPEC, species, speciesName, minWebs, maxWebs ); + } + + public static class Web extends Config.AbstractCategory { + + public final IntField.RandomRange webCount; + + Web( ToastConfigSpec parent, MobFamily.Species species, String speciesName, int minWebs, int maxWebs ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + webCount = new IntField.RandomRange( + SPEC.define( new IntField( "webs.min", minWebs, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of cobwebs " + speciesName + " can place." ) ), + SPEC.define( new IntField( "webs.max", maxWebs, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/WildfireBlazeSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/WildfireBlazeSpeciesConfig.java new file mode 100644 index 0000000..bb162f7 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/WildfireBlazeSpeciesConfig.java @@ -0,0 +1,47 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class WildfireBlazeSpeciesConfig extends BlazeSpeciesConfig { + + public final Wildfire WILDFIRE; + + /** Builds the config spec that should be used for this config. */ + public WildfireBlazeSpeciesConfig( MobFamily.Species species, int fireballBurstCount, int fireballBurstDelay, + int minBabies, int maxBabies, int minSummons, int maxSummons ) { + super( species, fireballBurstCount, fireballBurstDelay ); + + WILDFIRE = new Wildfire( SPEC, species, speciesName, minBabies, maxBabies, minSummons, maxSummons ); + } + + public static class Wildfire extends Config.AbstractCategory { + + public final IntField.RandomRange babies; + + public final IntField.RandomRange summons; + + Wildfire( ToastConfigSpec parent, MobFamily.Species species, String speciesName, + int minBabies, int maxBabies, int minSummons, int maxSummons ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + babies = new IntField.RandomRange( + SPEC.define( new IntField( "babies.min", minBabies, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of babies " + speciesName + " spawn on death." ) ), + SPEC.define( new IntField( "babies.max", maxBabies, IntField.Range.NON_NEGATIVE ) ) + ); + + SPEC.newLine(); + + summons = new IntField.RandomRange( + SPEC.define( new IntField( "summons.min", minSummons, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of times " + speciesName + " can summon minions." ) ), + SPEC.define( new IntField( "summons.max", maxSummons, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/WildsWitchSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/WildsWitchSpeciesConfig.java new file mode 100644 index 0000000..5abe327 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/WildsWitchSpeciesConfig.java @@ -0,0 +1,58 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.IntField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +public class WildsWitchSpeciesConfig extends SpeciesConfig { + + public final Wilds WILDS; + + /** Builds the config spec that should be used for this config. */ + public WildsWitchSpeciesConfig( MobFamily.Species species, int minMounts, int maxMounts, + int minSwarms, int maxSwarms, int minSwarmSize, int maxSwarmSize ) { + super( species ); + + WILDS = new Wilds( SPEC, species, speciesName, minMounts, maxMounts, minSwarms, maxSwarms, minSwarmSize, maxSwarmSize ); + } + + public static class Wilds extends Config.AbstractCategory { + + public final IntField.RandomRange mounts; + + public final IntField.RandomRange swarms; + + public final IntField.RandomRange swarmSize; + + Wilds( ToastConfigSpec parent, MobFamily.Species species, String speciesName, + int minMounts, int maxMounts, int minSwarms, int maxSwarms, int minSwarmSize, int maxSwarmSize ) { + super( parent, ConfigUtil.camelCaseToLowerUnderscore( species.specialVariantName ), + "Options specific to " + speciesName + "." ); + + mounts = new IntField.RandomRange( + SPEC.define( new IntField( "mounts.min", minMounts, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of times " + speciesName + " can summon a spider mount." ) ), + SPEC.define( new IntField( "mounts.max", maxMounts, IntField.Range.NON_NEGATIVE ) ) + ); + + SPEC.newLine(); + + swarms = new IntField.RandomRange( + SPEC.define( new IntField( "swarms.min", minSwarms, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of times " + speciesName + " can summon a spider swarm." ) ), + SPEC.define( new IntField( "swarms.max", maxSwarms, IntField.Range.NON_NEGATIVE ) ) + ); + + SPEC.newLine(); + + swarmSize = new IntField.RandomRange( + SPEC.define( new IntField( "swarm_size.min", minSwarmSize, IntField.Range.NON_NEGATIVE, + "The minimum and maximum (inclusive) number of spiders " + speciesName + " spawn with each swarm.", + "Note that this is rolled on the summoner's spawn, not each time a swarm is summoned." ) ), + SPEC.define( new IntField( "swarm_size.max", maxSwarmSize, IntField.Range.NON_NEGATIVE ) ) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/species/ZombieSpeciesConfig.java b/src/main/java/fathertoast/specialmobs/common/config/species/ZombieSpeciesConfig.java new file mode 100644 index 0000000..5d36082 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/species/ZombieSpeciesConfig.java @@ -0,0 +1,45 @@ +package fathertoast.specialmobs.common.config.species; + +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.field.DoubleField; +import fathertoast.specialmobs.common.config.file.ToastConfigSpec; +import fathertoast.specialmobs.common.config.util.ConfigUtil; + +/** + * This is the base species config for zombies, drowned, and zombified piglins. + */ +public class ZombieSpeciesConfig extends SpeciesConfig { + + public final Zombies ZOMBIES; + + /** Builds the config spec that should be used for this config. */ + public ZombieSpeciesConfig( MobFamily.Species species, double bowChance, double shieldChance ) { + super( species ); + + ZOMBIES = new Zombies( SPEC, species, speciesName, bowChance, shieldChance ); + } + + public static class Zombies extends Config.AbstractCategory { + + public final DoubleField bowEquipChance; + + public final DoubleField shieldEquipChance; + + Zombies( ToastConfigSpec parent, MobFamily.Species species, String speciesName, double bowChance, double shieldChance ) { + super( parent, ConfigUtil.noSpaces( species.family.configName ), + "Options standard to all " + species.family.configName + "." ); + + // Automatically set the default bow chance to 0% if the mob has ranged attacks disabled by default + final double effectiveDefault = species.bestiaryInfo.rangedAttackMaxRange > 0.0F ? bowChance : 0.0; + bowEquipChance = SPEC.define( new DoubleField( "bow_chance", effectiveDefault, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn with a bow, which enables their ranged attack (if max range > 0)." ) ); + + SPEC.newLine(); + + shieldEquipChance = SPEC.define( new DoubleField( "shield_chance", shieldChance, DoubleField.Range.PERCENT, + "Chance for " + speciesName + " to spawn with a shield if they did not spawn with a bow.", + "Shield users have a 33% chance to block frontal attacks (100% vs. long range attacks) and can be broken by axes." ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/AttributeEntry.java b/src/main/java/fathertoast/specialmobs/common/config/util/AttributeEntry.java new file mode 100644 index 0000000..cbddd6c --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/util/AttributeEntry.java @@ -0,0 +1,75 @@ +package fathertoast.specialmobs.common.config.util; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.AttributeModifierMap; +import net.minecraft.entity.ai.attributes.Attributes; +import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; + +/** + * One attribute-operation-value entry in an attribute list. + */ +@SuppressWarnings( "unused" ) +public class AttributeEntry { + /** The attribute this entry is defined for. */ + public final Attribute ATTRIBUTE; + /** True if the value should be multiplied to the base attribute value (as opposed to added). */ + public final boolean MULTIPLY; + /** The value given to this entry. */ + public final double VALUE; + + /** The class this entry is defined for. This is not assigned until a world has been loaded. */ + Class entityClass; + + /** Creates an entry with the specified values using the addition operation. Incompatible with move speed. Used for creating default configs. */ + public static AttributeEntry add( Attribute attribute, double value ) { + if( attribute.equals( Attributes.MOVEMENT_SPEED ) ) + throw new IllegalArgumentException( "Move speed should not be added!" ); + return new AttributeEntry( attribute, false, value ); + } + + /** Creates an entry with the specified values using the multiplication operation. Used for creating default configs. */ + public static AttributeEntry mult( Attribute attribute, double value ) { return new AttributeEntry( attribute, true, value ); } + + /** Creates an entry with the specified values. */ + private AttributeEntry( Attribute attribute, boolean multiply, double value ) { + ATTRIBUTE = attribute; + MULTIPLY = multiply; + VALUE = value; + } + + /** + * @return The string representation of this entity list entry, as it would appear in a config file. + *

+ * Format is "registry_key operation value", operation may be +, -, or *. + */ + @Override + public String toString() { + // Start with the attribute registry key + ResourceLocation resource = ForgeRegistries.ATTRIBUTES.getKey( ATTRIBUTE ); + StringBuilder str = new StringBuilder( resource == null ? "null" : resource.toString() ).append( ' ' ); + // Append operation and value + if( MULTIPLY ) str.append( "* " ).append( VALUE ); + else if( VALUE < 0.0 ) str.append( "- " ).append( -VALUE ); + else str.append( "+ " ).append( VALUE ); + return str.toString(); + } + + /** Applies this attribute change to the entity attribute builder. */ + public void apply( AttributeModifierMap.MutableAttribute builder ) { apply( builder.builder.get( ATTRIBUTE ) ); } + + /** Applies this attribute change to the entity. */ + public void apply( LivingEntity entity ) { apply( entity.getAttribute( ATTRIBUTE ) ); } + + /** Applies this attribute change to the attribute instance. Assumes that the instance is for this entry's target attribute. */ + private void apply( ModifiableAttributeInstance attributeInstance ) { + if( attributeInstance == null ) + throw new IllegalStateException( "Attempted to modify non-registered attribute " + ATTRIBUTE.getDescriptionId() ); + + if( MULTIPLY ) attributeInstance.setBaseValue( attributeInstance.getBaseValue() * VALUE ); + else attributeInstance.setBaseValue( attributeInstance.getBaseValue() + VALUE ); + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/AttributeList.java b/src/main/java/fathertoast/specialmobs/common/config/util/AttributeList.java new file mode 100644 index 0000000..96665d2 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/util/AttributeList.java @@ -0,0 +1,57 @@ +package fathertoast.specialmobs.common.config.util; + +import fathertoast.specialmobs.common.config.field.IStringArray; +import fathertoast.specialmobs.common.config.file.TomlHelper; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.attributes.AttributeModifierMap; + +import java.util.ArrayList; +import java.util.List; + +public class AttributeList implements IStringArray { + /** The attribute-operation-value entries in this list. */ + private final AttributeEntry[] ENTRIES; + + /** + * Create a new attribute list from a list of entries. + */ + public AttributeList( List entries ) { this( entries.toArray( new AttributeEntry[0] ) ); } + + /** + * Create a new entity list from an array of entries. Used for creating default configs. + */ + public AttributeList( AttributeEntry... entries ) { ENTRIES = entries; } + + /** @return A string representation of this object. */ + @Override + public String toString() { return TomlHelper.toLiteral( toStringList().toArray() ); } + + /** @return Returns true if this object has the same value as another object. */ + @Override + public boolean equals( Object other ) { + if( !(other instanceof AttributeList) ) return false; + // Compare by the string list view of the object + return toStringList().equals( ((AttributeList) other).toStringList() ); + } + + /** @return A list of strings that will represent this object when written to a toml file. */ + @Override + public List toStringList() { + // Create a list of the entries in string format + final List list = new ArrayList<>( ENTRIES.length ); + for( AttributeEntry entry : ENTRIES ) { + list.add( entry.toString() ); + } + return list; + } + + /** Applies all attribute changes in this list to the entity attribute builder. */ + public void apply( AttributeModifierMap.MutableAttribute builder ) { + for( AttributeEntry entry : ENTRIES ) entry.apply( builder ); + } + + /** Applies all attribute changes in this list to the entity. */ + public void apply( LivingEntity entity ) { + for( AttributeEntry entry : ENTRIES ) entry.apply( entity ); + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/BlockEntry.java b/src/main/java/fathertoast/specialmobs/common/config/util/BlockEntry.java index 5f58588..bb2ecfa 100644 --- a/src/main/java/fathertoast/specialmobs/common/config/util/BlockEntry.java +++ b/src/main/java/fathertoast/specialmobs/common/config/util/BlockEntry.java @@ -14,7 +14,7 @@ import net.minecraftforge.registries.ForgeRegistries; import java.util.*; /** - * One entity-value entry in an entity list. + * One block state entry in a block list. */ @SuppressWarnings( "unused" ) public class BlockEntry implements Cloneable { diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/ConfigUtil.java b/src/main/java/fathertoast/specialmobs/common/config/util/ConfigUtil.java new file mode 100644 index 0000000..6c45cd8 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/util/ConfigUtil.java @@ -0,0 +1,36 @@ +package fathertoast.specialmobs.common.config.util; + +public abstract class ConfigUtil { + + /** The plus or minus symbol (+/-). */ + public static final String PLUS_OR_MINUS = "\u00b1"; + /** The less than or equal to symbol (<=). */ + public static final String LESS_OR_EQUAL = "\u2264"; + /** The greater than or equal to symbol (>=). */ + public static final String GREATER_OR_EQUAL = "\u2265"; + + /** @return The string with all spaces replaced by underscores. Useful for file names. */ + public static String noSpaces( String str ) { return str.replace( ' ', '_' ); } + + /** @return The string converted from camel case to lower space case; e.g., "UpperCamelCase" returns "upper camel case". */ + public static String camelCaseToLowerSpace( String str ) { + final StringBuilder spacedStr = new StringBuilder(); + for( int i = 0; i < str.length(); i++ ) { + final char c = str.charAt( i ); + if( Character.isUpperCase( c ) ) { + if( i > 0 ) spacedStr.append( ' ' ); + spacedStr.append( Character.toLowerCase( c ) ); + } + else { + spacedStr.append( c ); + } + } + return spacedStr.toString(); + } + + /** @return The string converted from camel case to lower underscore case; e.g., "UpperCamelCase" returns "upper_camel_case". */ + public static String camelCaseToLowerUnderscore( String str ) { return noSpaces( camelCaseToLowerSpace( str ) ); } + + /** @return The string, but with the first character changed to upper case. */ + public static String properCase( String str ) { return str.substring( 0, 1 ).toUpperCase() + str.substring( 1 ); } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/LazyRegistryEntryList.java b/src/main/java/fathertoast/specialmobs/common/config/util/LazyRegistryEntryList.java new file mode 100644 index 0000000..25e97ab --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/util/LazyRegistryEntryList.java @@ -0,0 +1,121 @@ +package fathertoast.specialmobs.common.config.util; + +import fathertoast.specialmobs.common.config.field.AbstractConfigField; +import fathertoast.specialmobs.common.config.field.IStringArray; +import fathertoast.specialmobs.common.config.file.TomlHelper; +import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import java.util.*; + +/** + * A list of entries used to match registry entries. Can safely be loaded before its target registry is loaded, but + * is not able to error check as well. + *

+ * See also: {@link net.minecraftforge.registries.ForgeRegistries} + */ +@SuppressWarnings( "unused" ) +public class LazyRegistryEntryList> implements IStringArray { + /** The registry this list acts as a subset of. */ + private final IForgeRegistry REGISTRY; + + /** The entries in this list. */ + private final Set UNDERLYING_SET = new HashSet<>(); + /** The list used to write back to file. */ + private final List PRINT_LIST = new ArrayList<>(); + + /** + * Create a new registry entry list from an array of entries. Used for creating default configs. + *

+ * This method of creation can not take advantage of the * notation. + */ + @SafeVarargs + public LazyRegistryEntryList( IForgeRegistry registry, T... entries ) { + REGISTRY = registry; + for( T entry : entries ) { + if( UNDERLYING_SET.add( entry ) ) PRINT_LIST.add( SpecialMobs.toString( registry.getKey( entry ) ) ); + } + } + + /** + * Create a new registry entry list from a list of registry key strings. + */ + public LazyRegistryEntryList( AbstractConfigField field, IForgeRegistry registry, List entries ) { + REGISTRY = registry; + for( String line : entries ) { + if( line.endsWith( "*" ) ) { + // Handle special case; add all entries in namespace + if( !mergeFromNamespace( line.substring( 0, line.length() - 1 ) ) ) { + // Don't delete this kind of entry + SpecialMobs.LOG.warn( "Namespace entry for {} \"{}\" did not match anything! Questionable entry: {}", + field.getClass(), field.getKey(), line ); + } + PRINT_LIST.add( line ); + } + else { + // Add a single registry entry + final ResourceLocation regKey = new ResourceLocation( line ); + if( mergeFrom( regKey ) ) { + PRINT_LIST.add( regKey.toString() ); + } + else { + SpecialMobs.LOG.warn( "Invalid entry for {} \"{}\"! Deleting entry. Invalid entry: {}", + field.getClass(), field.getKey(), line ); + } + } + } + } + + /** @return The registry this list draws from. */ + public IForgeRegistry getRegistry() { return REGISTRY; } + + /** @return The entries in this list. */ + public Set getEntries() { return Collections.unmodifiableSet( UNDERLYING_SET ); } + + /** @return A string representation of this object. */ + @Override + public String toString() { + return TomlHelper.toLiteral( PRINT_LIST.toArray() ); + } + + /** @return Returns true if this object has the same value as another object. */ + @Override + public boolean equals( Object other ) { + if( !(other instanceof LazyRegistryEntryList) ) return false; + // Compare by the registries used and string list view of the object + return getRegistry() == ((LazyRegistryEntryList) other).getRegistry() && + toStringList().equals( ((LazyRegistryEntryList) other).toStringList() ); + } + + /** @return A list of strings that will represent this object when written to a toml file. */ + @Override + public List toStringList() { return PRINT_LIST; } + + /** @return Returns true if there are no entries in this list. */ + public boolean isEmpty() { return UNDERLYING_SET.isEmpty(); } + + /** @return Returns true if the entry is contained in this list. */ + public boolean contains( T entry ) { return UNDERLYING_SET.contains( entry ); } + + /** @return Adds the registry entry if it exists and isn't already present, returns true if successful. */ + private boolean mergeFrom( ResourceLocation regKey ) { + final T entry = REGISTRY.getValue( regKey ); + return entry != null && UNDERLYING_SET.add( entry ); + } + + /** + * @param namespace Merges all registry entries with keys that start with a namespace into this list. + * @return True if any registry entries were actually added. + */ + private boolean mergeFromNamespace( String namespace ) { + boolean foundAny = false; + for( ResourceLocation regKey : REGISTRY.getKeys() ) { + if( regKey.toString().startsWith( namespace ) ) { + if( mergeFrom( regKey ) ) foundAny = true; + } + } + return foundAny; + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/config/util/RegistryEntryList.java b/src/main/java/fathertoast/specialmobs/common/config/util/RegistryEntryList.java new file mode 100644 index 0000000..1f20384 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/config/util/RegistryEntryList.java @@ -0,0 +1,120 @@ +package fathertoast.specialmobs.common.config.util; + +import fathertoast.specialmobs.common.config.field.AbstractConfigField; +import fathertoast.specialmobs.common.config.field.IStringArray; +import fathertoast.specialmobs.common.config.file.TomlHelper; +import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import java.util.*; + +/** + * A list of entries used to match registry entries. + *

+ * See also: {@link net.minecraftforge.registries.ForgeRegistries} + */ +@SuppressWarnings( "unused" ) +public class RegistryEntryList> implements IStringArray { + /** The registry this list acts as a subset of. */ + private final IForgeRegistry REGISTRY; + + /** The entries in this list. */ + private final Set UNDERLYING_SET = new HashSet<>(); + /** The list used to write back to file. */ + private final List PRINT_LIST = new ArrayList<>(); + + /** + * Create a new registry entry list from an array of entries. Used for creating default configs. + *

+ * This method of creation can not take advantage of the * notation. + */ + @SafeVarargs + public RegistryEntryList( IForgeRegistry registry, T... entries ) { + REGISTRY = registry; + for( T entry : entries ) { + if( UNDERLYING_SET.add( entry ) ) PRINT_LIST.add( SpecialMobs.toString( registry.getKey( entry ) ) ); + } + } + + /** + * Create a new registry entry list from a list of registry key strings. + */ + public RegistryEntryList( AbstractConfigField field, IForgeRegistry registry, List entries ) { + REGISTRY = registry; + for( String line : entries ) { + if( line.endsWith( "*" ) ) { + // Handle special case; add all entries in namespace + if( !mergeFromNamespace( line.substring( 0, line.length() - 1 ) ) ) { + // Don't delete this kind of entry + SpecialMobs.LOG.warn( "Namespace entry for {} \"{}\" did not match anything! Questionable entry: {}", + field.getClass(), field.getKey(), line ); + } + PRINT_LIST.add( line ); + } + else { + // Add a single registry entry + final ResourceLocation regKey = new ResourceLocation( line ); + if( mergeFrom( regKey ) ) { + PRINT_LIST.add( regKey.toString() ); + } + else { + SpecialMobs.LOG.warn( "Invalid entry for {} \"{}\"! Deleting entry. Invalid entry: {}", + field.getClass(), field.getKey(), line ); + } + } + } + } + + /** @return The registry this list draws from. */ + public IForgeRegistry getRegistry() { return REGISTRY; } + + /** @return The entries in this list. */ + public Set getEntries() { return Collections.unmodifiableSet( UNDERLYING_SET ); } + + /** @return A string representation of this object. */ + @Override + public String toString() { + return TomlHelper.toLiteral( PRINT_LIST.toArray() ); + } + + /** @return Returns true if this object has the same value as another object. */ + @Override + public boolean equals( Object other ) { + if( !(other instanceof RegistryEntryList) ) return false; + // Compare by the registries used and string list view of the object + return getRegistry() == ((RegistryEntryList) other).getRegistry() && + toStringList().equals( ((RegistryEntryList) other).toStringList() ); + } + + /** @return A list of strings that will represent this object when written to a toml file. */ + @Override + public List toStringList() { return PRINT_LIST; } + + /** @return Returns true if there are no entries in this list. */ + public boolean isEmpty() { return UNDERLYING_SET.isEmpty(); } + + /** @return Returns true if the entry is contained in this list. */ + public boolean contains( T entry ) { return UNDERLYING_SET.contains( entry ); } + + /** @return Adds the registry entry if it exists and isn't already present, returns true if successful. */ + private boolean mergeFrom( ResourceLocation regKey ) { + final T entry = REGISTRY.getValue( regKey ); + return entry != null && UNDERLYING_SET.add( entry ); + } + + /** + * @param namespace Merges all registry entries with keys that start with a namespace into this list. + * @return True if any registry entries were actually added. + */ + private boolean mergeFromNamespace( String namespace ) { + boolean foundAny = false; + for( ResourceLocation regKey : REGISTRY.getKeys() ) { + if( regKey.toString().startsWith( namespace ) ) { + if( mergeFrom( regKey ) ) foundAny = true; + } + } + return foundAny; + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/core/SpecialMobs.java b/src/main/java/fathertoast/specialmobs/common/core/SpecialMobs.java index 908d07a..9a6ca17 100644 --- a/src/main/java/fathertoast/specialmobs/common/core/SpecialMobs.java +++ b/src/main/java/fathertoast/specialmobs/common/core/SpecialMobs.java @@ -39,17 +39,19 @@ public class SpecialMobs { * o dimension-sensitive configs * o environment-sensitive configs * ? natural spawning + * + potions + * + vulnerability (opposite of resistance) * o entities * - nbt-driven capabilities (special mob data) * o fish hook - * o bug projectile + * o bug spit * + bestiary - * ? configurable stats + * - configurable stats * - monster families (see doc for specifics) * - creepers * - chance to spawn charged during thunderstorms * + scope - * - zombies + * - zombies TODO zombie villager renderer * o villager infection * + transformations * - ranged attack AI (using bow) @@ -57,25 +59,28 @@ public class SpecialMobs { * + drowned * - zombified piglins * - ranged attack AI (using bow) + * + ranged attack AI (using crossbow) * - use shields * - skeletons * - use shields + * - melee chance * - babies * - wither skeletons * - use shields + * - bow chance * - babies * - slimes * - smallest size can deal damage * - magma cubes * - spiders - * o ranged attack AI + * o ranged attack AI (spitter) * - cave spiders - * o ranged attack AI + * o ranged attack AI (spitter) * - silverfish - * ? ranged attack AI + * + ranged attack AI (spitter) * + puffer * - endermen - * - witches + * - witches TODO inject ranged attack stats * - ability to equip held items * - uses splash speed instead of regular * - ghasts @@ -109,6 +114,8 @@ public class SpecialMobs { public SpecialMobs() { Config.initialize(); + MobFamily.initBestiary(); + packetHandler.registerMessages(); //MinecraftForge.EVENT_BUS.register( new SMEventListener() ); @@ -121,8 +128,6 @@ public class SpecialMobs { SMEntities.REGISTRY.register( eventBus ); SMItems.REGISTRY.register( eventBus ); - - MobFamily.initBestiary(); } // TODO - This could very well help out the config malformation issue 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 cd7be18..f07e43f 100644 --- a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java +++ b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java @@ -7,6 +7,7 @@ import fathertoast.specialmobs.common.util.AnnotationHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; +import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.registries.DeferredRegister; @@ -15,10 +16,10 @@ import net.minecraftforge.registries.ForgeRegistries; public class SMEntities { public static final DeferredRegister> REGISTRY = DeferredRegister.create( ForgeRegistries.ENTITIES, SpecialMobs.MOD_ID ); - + /** Misc entities */ - public static final RegistryObject> CORPOREAL_FIREBALL = register("corporeal_shift_fireball", - EntityType.Builder.of(CorporealShiftFireballEntity::new, EntityClassification.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(3)); + public static final RegistryObject> CORPOREAL_FIREBALL = register( "corporeal_shift_fireball", + EntityType.Builder.of( CorporealShiftFireballEntity::new, EntityClassification.MISC ).sized( 1.0F, 1.0F ).clientTrackingRange( 4 ).updateInterval( 3 ) ); /** Registers an entity type to the deferred register. */ public static RegistryObject> register( String name, EntityType.Builder builder ) { @@ -28,8 +29,11 @@ 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 species : MobFamily.getAllSpecies() ) - event.put( species.entityType.get(), AnnotationHelper.createAttributes( species ) ); + for( MobFamily.Species species : MobFamily.getAllSpecies() ) { + final AttributeModifierMap.MutableAttribute attributes = AnnotationHelper.createAttributes( species ); + species.config.GENERAL.attributeChanges.apply( attributes ); + event.put( species.entityType.get(), attributes.build() ); + } } /** Sets the natural spawn placement rules for entity types. */ diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ISpecialMob.java b/src/main/java/fathertoast/specialmobs/common/entity/ISpecialMob.java index 754c624..edae987 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ISpecialMob.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ISpecialMob.java @@ -1,13 +1,17 @@ package fathertoast.specialmobs.common.entity; +import fathertoast.specialmobs.common.bestiary.MobFamily; import net.minecraft.entity.LivingEntity; import net.minecraft.pathfinding.PathNodeType; -import net.minecraft.util.ResourceLocation; public interface ISpecialMob> { + /** @return This mob's special data. */ SpecialMobData getSpecialData(); + /** @return This mob's species. */ + MobFamily.Species getSpecies(); + /** @return The experience that should be dropped by this entity. */ int getExperience(); @@ -16,7 +20,4 @@ public interface ISpecialMob> { /** Sets the entity's pathfinding malus for a particular node type; negative value is un-walkable. */ void setPathfindingMalus( PathNodeType nodeType, float malus ); - - /** @return All default textures for this entity. */ - ResourceLocation[] getDefaultTextures(); } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/MobHelper.java b/src/main/java/fathertoast/specialmobs/common/entity/MobHelper.java index 691e9ab..c79d186 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/MobHelper.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/MobHelper.java @@ -1,11 +1,13 @@ package fathertoast.specialmobs.common.entity; -import fathertoast.specialmobs.common.util.References; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.entity.creeper._SpecialCreeperEntity; import net.minecraft.block.FlowingFluidBlock; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.monster.CreeperEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.fluid.Fluid; @@ -52,6 +54,16 @@ public final class MobHelper { new EffectInstance( Effects.POISON, 1, 0 ) // Keep this option last for easy disable (by cave spiders) }; + /** Charges a creeper, potentially supercharging it. */ + public static void charge( CreeperEntity creeper ) { + if( creeper instanceof _SpecialCreeperEntity ) { + ((_SpecialCreeperEntity) creeper).charge(); + } + else { + creeper.getEntityData().set( CreeperEntity.DATA_IS_POWERED, true ); + } + } + /** @return True if the damage source can deal normal damage to vampire-type mobs (e.g., wooden or smiting weapons). */ public static boolean isDamageSourceIneffectiveAgainstVampires( DamageSource source ) { if( source != null ) { @@ -184,8 +196,8 @@ public final class MobHelper { public static EffectInstance nextPlagueEffect( Random random, World world ) { final int duration = MobHelper.getDebuffDuration( world.getDifficulty() ); - //final EffectInstance potion = PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length - (Config.get().GENERAL.DISABLE_NAUSEA ? 1 : 0) )]; TODO config - final EffectInstance potion = PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length )]; + final EffectInstance potion = PLAGUE_EFFECTS[random.nextInt( PLAGUE_EFFECTS.length - + (Config.MAIN.GENERAL.enableNausea.get() ? 0 : 1) )]; return new EffectInstance( potion.getEffect(), duration * potion.getDuration(), potion.getAmplifier() ); } @@ -248,7 +260,7 @@ public final class MobHelper { Vector3d targetVec = sourcePos.vectorTo( blocker.position() ).normalize(); targetVec = new Vector3d( targetVec.x, 0.0, targetVec.z ); if( targetVec.dot( lookVec ) < 0.0 ) { - blocker.level.playSound(null, blocker.getX() + 0.5D, blocker.getY(), blocker.getZ() + 0.5D, SoundEvents.SHIELD_BLOCK, SoundCategory.NEUTRAL, 0.9F, 1.0F); + blocker.level.playSound( null, blocker.getX() + 0.5D, blocker.getY(), blocker.getZ() + 0.5D, SoundEvents.SHIELD_BLOCK, SoundCategory.NEUTRAL, 0.9F, 1.0F ); if( needsShield && entity instanceof PlayerEntity ) { maybeDestroyShield( blocker, shield, shieldHand, ((PlayerEntity) entity).getMainHandItem() ); } @@ -268,7 +280,7 @@ public final class MobHelper { private static void maybeDestroyShield( LivingEntity blocker, ItemStack shield, Hand shieldHand, ItemStack weapon ) { if( !weapon.isEmpty() && !shield.isEmpty() && weapon.getItem() instanceof AxeItem && shield.getItem() == Items.SHIELD && blocker.getRandom().nextFloat() < 0.25F - EnchantmentHelper.getBlockEfficiency( blocker ) * 0.05F ) { - blocker.level.playSound(null, blocker.getX() + 0.5D, blocker.getY(), blocker.getZ() + 0.5D, SoundEvents.SHIELD_BREAK, SoundCategory.NEUTRAL, 0.9F, 1.0F); + blocker.level.playSound( null, blocker.getX() + 0.5D, blocker.getY(), blocker.getZ() + 0.5D, SoundEvents.SHIELD_BREAK, SoundCategory.NEUTRAL, 0.9F, 1.0F ); blocker.broadcastBreakEvent( shieldHand ); blocker.setItemInHand( shieldHand, ItemStack.EMPTY ); } diff --git a/src/main/java/fathertoast/specialmobs/common/entity/SpecialMobData.java b/src/main/java/fathertoast/specialmobs/common/entity/SpecialMobData.java index be28560..e511d5a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/SpecialMobData.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/SpecialMobData.java @@ -1,12 +1,14 @@ package fathertoast.specialmobs.common.entity; +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +import fathertoast.specialmobs.common.bestiary.MobFamily; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.core.SpecialMobs; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.monster.SpiderEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.StringNBT; @@ -14,11 +16,12 @@ import net.minecraft.network.datasync.DataParameter; import net.minecraft.pathfinding.PathNodeType; import net.minecraft.potion.Effect; import net.minecraft.potion.EffectInstance; -import net.minecraft.potion.Effects; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.living.PotionEvent; +import net.minecraftforge.registries.ForgeRegistries; +import java.util.Collection; import java.util.HashSet; import static fathertoast.specialmobs.common.util.References.*; @@ -47,11 +50,6 @@ public class SpecialMobData> { /** Data manager parameter for render scale. */ private final DataParameter renderScale; - /** The base collision box scale of this variant's family. */ - private final float familyScale; - /** The base collision box scale of this variant. */ - private float baseScale; - /** The base texture of the entity. */ private ResourceLocation texture; /** The glowing eyes texture of the entity. */ @@ -61,43 +59,17 @@ public class SpecialMobData> { /** True if the textures need to be sent to the client. */ private boolean updateTextures; - /** The damage the entity uses for its ranged attacks, when applicable. */ - public float rangedAttackDamage; - /** The spread (inaccuracy) of the entity's ranged attacks. */ - public float rangedAttackSpread = 1.0F; - /** The movement speed multiplier the entity uses during its ranged attack ai. Requires an AI reload to take effect. */ - public float rangedWalkSpeed = 1.0F; - /** The delay (in ticks) before a new ranged attack can begin after firing. Requires an AI reload to take effect. */ - public int rangedAttackCooldown; - /** - * The delay (in ticks) between each ranged attack at maximum delay. Requires an AI reload to take effect. - * Unused for bow attacks. For fireball attacks, this is the cooldown + charge time. - * For all other attacks, this is the cooldown at maximum range (scaled down to the minimum cooldown at point-blank). - */ - public int rangedAttackMaxCooldown; - /** - * The maximum distance (in blocks) the entity can fire ranged attacks from. Requires an ai reload to take effect. - * Ranged ai can only be used if this stat is greater than 0. Does not change aggro range. - */ - public float rangedAttackMaxRange; - /** The rate this mob regenerates health (ticks per 1 health). Off if 0 or less. */ private int healTimeMax; /** Counter to the next heal, if healTimeMax is greater than 0. */ private int healTime; /** Proportion of fall damage taken. */ - private float fallDamageMultiplier = 1.0F; - + private float fallDamageMultiplier; /** Whether the entity is immune to fire damage. */ private boolean isImmuneToFire; /** Whether the entity is immune to being set on fire. */ private boolean isImmuneToBurning; - /** Whether the entity can be leashed. */ - private boolean allowLeashing; - /** Whether the entity does not trigger pressure plates. */ - private boolean ignorePressurePlates; - /** Whether the entity can breathe under water. */ private boolean canBreatheInWater; /** Whether the entity can ignore pushing from flowing water. */ @@ -105,44 +77,79 @@ public class SpecialMobData> { /** Whether the entity is damaged when wet. */ private boolean isDamagedByWater; - /** List of blocks that the entity cannot be stuck in. */ - private final HashSet immuneToStickyBlocks = new HashSet<>(); - /** List of potions that cannot be applied to the entity. */ - private final HashSet immuneToPotions = new HashSet<>(); + /** Whether the entity can be leashed. */ + private boolean allowLeashing; + /** Whether the entity does not trigger pressure plates. */ + private boolean ignorePressurePlates; + /** Set of blocks that the entity cannot be stuck in. */ + private final HashSet immuneToStickyBlocks = new HashSet<>(); + /** Set of potions that cannot be applied to the entity. */ + private final HashSet immuneToPotions = new HashSet<>(); + + /** The damage the entity uses for its ranged attacks, when applicable. */ + private float rangedAttackDamage; + /** The spread (inaccuracy) of the entity's ranged attacks. */ + private float rangedAttackSpread; + /** The movement speed multiplier the entity uses during its ranged attack ai. Requires an AI reload to take effect. */ + private float rangedWalkSpeed; + /** The delay (in ticks) before a ranged attack can be used. Requires an AI reload to take effect. */ + private int rangedAttackCooldown; + /** + * The delay (in ticks) between each ranged attack at maximum delay. Requires an AI reload to take effect. + * Unused for bow attacks. For fireball attacks, this is "refire" time. + * For spit attacks, this is the cooldown at maximum range (scaled down to the minimum cooldown at point-blank). + */ + private int rangedAttackMaxCooldown; + /** + * The maximum distance (in blocks) the entity can fire ranged attacks from. Requires an ai reload to take effect. + * Ranged ai can only be used if this stat is greater than 0. Does not change aggro range. + */ + private float rangedAttackMaxRange; /** * Constructs a SpecialMobData to store generic data about a mob. *

* This constructor should be called during data watcher definitions, and defining the 'render scale' data watcher - * parameter is the only thing actually done while constructing. + * parameter and setting up AI stats are the only things actually done while constructing. *

- * The #initialize() method must be called later on to complete initialization (e.g. in the entity constructor). + * The #initialize() method must be called later on to complete initialization (in the entity constructor). * - * @param entity The entity to store data for. - * @param scale Data parameter for storing the render scale. - * @param familyBaseScale Base render scale. Typically 1.0F. + * @param entity The entity to store data for. + * @param scale Data parameter for storing the render scale. */ - public SpecialMobData( T entity, DataParameter scale, float familyBaseScale ) { + public SpecialMobData( T entity, DataParameter scale ) { theEntity = entity; renderScale = scale; - - familyScale = baseScale = familyBaseScale; - - setTextures( entity.getDefaultTextures() ); - entity.getEntityData().define( renderScale, nextScale() ); + + final SpeciesConfig.General config = theEntity.getSpecies().config.GENERAL; + setRangedAttackDamage( config.rangedAttackDamage == null ? -1.0F : (float) config.rangedAttackDamage.get() ); + setRangedAttackSpread( config.rangedAttackSpread == null ? -1.0F : (float) config.rangedAttackSpread.get() ); + setRangedWalkSpeed( config.rangedWalkSpeed == null ? -1.0F : (float) config.rangedWalkSpeed.get() ); + setRangedAttackCooldown( config.rangedAttackCooldown == null ? -1 : config.rangedAttackCooldown.get() ); + setRangedAttackMaxCooldown( config.rangedAttackMaxCooldown == null ? -1 : config.rangedAttackMaxCooldown.get() ); + setRangedAttackMaxRange( config.rangedAttackMaxRange == null ? -1.0F : (float) config.rangedAttackMaxRange.get() ); } - /** Called to finish initialization, since we can only define data watcher params in the constructor. */ public void initialize() { - setImmuneToFire( theEntity.getType().fireImmune() ); - if( theEntity.getMobType() == CreatureAttribute.UNDEAD ) { - addPotionImmunity( Effects.REGENERATION, Effects.POISON ); - } - if( theEntity instanceof SpiderEntity ) { - addStickyBlockImmunity( Blocks.COBWEB ); - addPotionImmunity( Effects.POISON ); - } + final BestiaryInfo info = theEntity.getSpecies().bestiaryInfo; + texture = info.texture; + textureEyes = info.eyesTexture; + textureOverlay = info.overlayTexture; + + final SpeciesConfig.General config = theEntity.getSpecies().config.GENERAL; + theEntity.setExperience( config.experience.get() ); + setRegenerationTime( config.healTime.get() ); + setFallDamageMultiplier( (float) config.fallDamageMultiplier.get() ); + setImmuneToFire( config.isImmuneToFire.get() ); + setImmuneToBurning( config.isImmuneToBurning.get() ); + setCanBreatheInWater( config.canBreatheInWater.get() ); + setIgnoreWaterPush( config.ignoreWaterPush.get() ); + setDamagedByWater( config.isDamagedByWater.get() ); + setAllowLeashing( config.allowLeashing.get() ); + setIgnorePressurePlates( config.ignorePressurePlates.get() ); + addStickyBlockImmunity( config.immuneToStickyBlocks.get().getEntries() ); + addPotionImmunity( config.immuneToPotions.get().getEntries() ); } /** Copies all of the data from another mob, optionally copying texture(s). */ @@ -177,43 +184,29 @@ public class SpecialMobData> { } } - /** - * @return Whether this entity has a glowing eyes texture. - */ + /** @return Whether this entity has a glowing eyes texture. */ public boolean hasEyesTexture() { return textureEyes != null; } - /** - * @return Whether this entity has an overlay texture. - */ + /** @return Whether this entity has an overlay texture. */ public boolean hasOverlayTexture() { return textureOverlay != null; } - /** - * @return The base texture for the entity. - */ + /** @return The base texture for the entity. */ public ResourceLocation getTexture() { return texture; } - /** - * @return The glowing eyes texture for the entity. - */ + /** @return The glowing eyes texture for the entity. */ public ResourceLocation getTextureEyes() { return textureEyes; } - /** - * @return The overlay texture for the entity. - */ + /** @return The overlay texture for the entity. */ public ResourceLocation getTextureOverlay() { return textureOverlay; } - /** - * @param textures The new texture(s) to set for the entity. - */ + /** @param textures The new texture(s) to set for the entity. */ private void setTextures( ResourceLocation[] textures ) { texture = textures[0]; textureEyes = textures.length > 1 ? textures[1] : null; textureOverlay = textures.length > 2 ? textures[2] : null; } - /** - * @param textures The new texture(s) to load for the entity. Called when loaded from a packet. - */ + /** @param textures The new texture(s) to load for the entity. Called when loaded from a packet. */ public void loadTextures( String[] textures ) { try { loadTexture( textures[0] ); @@ -275,42 +268,51 @@ public class SpecialMobData> { } } - /** @return The render scale for the entity. */ + /** @return The render scale for the entity, including any applied random scaling. */ public float getRenderScale() { return theEntity.getEntityData().get( renderScale ); } + /** Sets the overall render scale for the entity. */ public void setRenderScale( float scale ) { - if( !theEntity.level.isClientSide ) { - theEntity.getEntityData().set( renderScale, scale ); - } + if( !theEntity.level.isClientSide ) theEntity.getEntityData().set( renderScale, scale ); } - public float getFamilyBaseScale() { return familyScale; } + //** @return The base render scale for the entity's mob family. */ + //public float getFamilyBaseScale() { return familyScale; } - public float getBaseScaleForPreScaledValues() { return getBaseScale() / getFamilyBaseScale(); } + //** @return The render scale for the entity without its family scale factored in; used to correct scaling for pre-scaled vanilla values. */ + //public float getBaseScaleForPreScaledValues() { return getBaseScale() / getFamilyBaseScale(); } - public float getBaseScale() { return baseScale; } - - public void setBaseScale( float newBaseScale ) { - baseScale = newBaseScale; - setRenderScale( nextScale() ); - } + /** @return The base render scale for the entity, which is a property of the mob species. */ + public float getBaseScale() { return theEntity.getSpecies().bestiaryInfo.baseScale; } + /** @return A random render scale based on config settings. */ private float nextScale() { - // if( Config.get().GENERAL.RANDOM_SCALING > 0.0F ) { TODO configs - // return baseScale * (1.0F + (theEntity.getRNG().nextFloat() - 0.5F) * Config.get().GENERAL.RANDOM_SCALING); - // } - return baseScale; + // Don't do random on client side stuff + if( theEntity.level == null || theEntity.level.isClientSide() ) return getBaseScale(); + + // Prioritize most specific value available + final MobFamily.Species species = theEntity.getSpecies(); + final double randomScaling; + if( species.config.GENERAL.randomScaling.get() >= 0.0 ) + randomScaling = species.config.GENERAL.randomScaling.get(); + else if( species.family.config.GENERAL.familyRandomScaling.get() >= 0.0 ) + randomScaling = species.family.config.GENERAL.familyRandomScaling.get(); + else + randomScaling = Config.MAIN.GENERAL.masterRandomScaling.get(); + + return randomScaling <= 0.0 ? getBaseScale() : + getBaseScale() * (1.0F + (theEntity.getRandom().nextFloat() - 0.5F) * 2.0F * (float) randomScaling); } - public void setRegenerationTime( int ticks ) { healTimeMax = ticks; } + private void setRegenerationTime( int ticks ) { healTimeMax = ticks; } public float getFallDamageMultiplier() { return fallDamageMultiplier; } - public void setFallDamageMultiplier( float value ) { fallDamageMultiplier = value; } + private void setFallDamageMultiplier( float value ) { fallDamageMultiplier = value; } public boolean isImmuneToFire() { return isImmuneToFire; } - public void setImmuneToFire( boolean value ) { + private void setImmuneToFire( boolean value ) { isImmuneToFire = value; if( value ) { theEntity.setPathfindingMalus( PathNodeType.LAVA, PathNodeType.WATER.getMalus() ); @@ -326,7 +328,7 @@ public class SpecialMobData> { public boolean isImmuneToBurning() { return isImmuneToBurning; } - public void setImmuneToBurning( boolean value ) { + private void setImmuneToBurning( boolean value ) { theEntity.clearFire(); isImmuneToBurning = value; if( value ) { @@ -341,23 +343,23 @@ public class SpecialMobData> { public boolean allowLeashing() { return allowLeashing; } - public void setAllowLeashing( boolean value ) { allowLeashing = value; } + private void setAllowLeashing( boolean value ) { allowLeashing = value; } public boolean ignorePressurePlates() { return ignorePressurePlates; } - public void setIgnorePressurePlates( boolean value ) { ignorePressurePlates = value; } + private void setIgnorePressurePlates( boolean value ) { ignorePressurePlates = value; } public boolean canBreatheInWater() { return canBreatheInWater; } - public void setCanBreatheInWater( boolean value ) { canBreatheInWater = value; } + private void setCanBreatheInWater( boolean value ) { canBreatheInWater = value; } public boolean ignoreWaterPush() { return ignoreWaterPush; } - public void setIgnoreWaterPush( boolean value ) { ignoreWaterPush = value; } + private void setIgnoreWaterPush( boolean value ) { ignoreWaterPush = value; } public boolean isDamagedByWater() { return isDamagedByWater; } - public void setDamagedByWater( boolean value ) { + private void setDamagedByWater( boolean value ) { isDamagedByWater = value; theEntity.setPathfindingMalus( PathNodeType.WATER, value ? PathNodeType.LAVA.getMalus() : PathNodeType.WATER.getMalus() ); } @@ -368,12 +370,10 @@ public class SpecialMobData> { * @param block The block state to test. * @return True if the block is allowed to apply its stuck speed multiplier. */ - public boolean canBeStuckIn( BlockState block ) { return !immuneToStickyBlocks.contains( block.getBlock().getDescriptionId() ); } + public boolean canBeStuckIn( BlockState block ) { return !immuneToStickyBlocks.contains( block.getBlock() ); } /** @param blocks The sticky block(s) to grant immunity from. */ - public void addStickyBlockImmunity( Block... blocks ) { - for( Block block : blocks ) immuneToStickyBlocks.add( block.getDescriptionId() ); - } + private void addStickyBlockImmunity( Collection blocks ) { immuneToStickyBlocks.addAll( blocks ); } /** * Tests a potion effect to see if it is applicable to the entity. @@ -387,14 +387,38 @@ public class SpecialMobData> { switch( event.getResult() ) { case DENY: return false; case ALLOW: return true; - default: return !immuneToPotions.contains( effect.getDescriptionId() ); + default: return !immuneToPotions.contains( effect.getEffect() ); } } /** @param effects The effect(s) to grant immunity from. */ - public void addPotionImmunity( Effect... effects ) { - for( Effect effect : effects ) immuneToPotions.add( effect.getDescriptionId() ); - } + private void addPotionImmunity( Collection effects ) { immuneToPotions.addAll( effects ); } + + public float getRangedAttackDamage() { return rangedAttackDamage; } + + public void setRangedAttackDamage( float value ) { rangedAttackDamage = value; } + + public float getRangedAttackSpread() { return rangedAttackSpread; } + + public void setRangedAttackSpread( float value ) { rangedAttackSpread = value; } + + public float getRangedWalkSpeed() { return rangedWalkSpeed; } + + public void setRangedWalkSpeed( float value ) { rangedWalkSpeed = value; } + + public int getRangedAttackCooldown() { return rangedAttackCooldown; } + + public void setRangedAttackCooldown( int value ) { rangedAttackCooldown = value; } + + public int getRangedAttackMaxCooldown() { return rangedAttackMaxCooldown; } + + public void setRangedAttackMaxCooldown( int value ) { rangedAttackMaxCooldown = value; } + + public float getRangedAttackMaxRange() { return rangedAttackMaxRange; } + + public void setRangedAttackMaxRange( float value ) { rangedAttackMaxRange = value; } + + public void disableRangedAttack() { setRangedAttackMaxRange( 0.0F ); } /** * Saves this data to NBT. @@ -403,22 +427,14 @@ public class SpecialMobData> { */ public void writeToNBT( CompoundNBT tag ) { tag.putFloat( TAG_RENDER_SCALE, getRenderScale() ); - tag.putInt( TAG_EXPERIENCE, theEntity.getExperience() ); - tag.putByte( TAG_REGENERATION, (byte) healTimeMax ); tag.putString( TAG_TEXTURE, texture.toString() ); tag.putString( TAG_TEXTURE_EYES, textureEyes == null ? "" : textureEyes.toString() ); tag.putString( TAG_TEXTURE_OVER, textureOverlay == null ? "" : textureOverlay.toString() ); - // Arrow AI - tag.putFloat( TAG_ARROW_DAMAGE, rangedAttackDamage ); - tag.putFloat( TAG_ARROW_SPREAD, rangedAttackSpread ); - tag.putFloat( TAG_ARROW_WALK_SPEED, rangedWalkSpeed ); - tag.putShort( TAG_ARROW_REFIRE_MIN, (short) rangedAttackCooldown ); - tag.putShort( TAG_ARROW_REFIRE_MAX, (short) rangedAttackMaxCooldown ); - tag.putFloat( TAG_ARROW_RANGE, rangedAttackMaxRange ); - - // Abilities + // Capabilities + tag.putInt( TAG_EXPERIENCE, theEntity.getExperience() ); + tag.putByte( TAG_REGENERATION, (byte) healTimeMax ); tag.putFloat( TAG_FALL_MULTI, getFallDamageMultiplier() ); tag.putBoolean( TAG_FIRE_IMMUNE, isImmuneToFire() ); tag.putBoolean( TAG_BURN_IMMUNE, isImmuneToBurning() ); @@ -429,16 +445,32 @@ public class SpecialMobData> { tag.putBoolean( TAG_WATER_DAMAGE, isDamagedByWater() ); final ListNBT stickyBlocksTag = new ListNBT(); - for( String blockName : immuneToStickyBlocks ) { - stickyBlocksTag.add( StringNBT.valueOf( blockName ) ); + for( Block block : immuneToStickyBlocks ) { + final ResourceLocation regKey = ForgeRegistries.BLOCKS.getKey( block ); + if( regKey != null ) stickyBlocksTag.add( StringNBT.valueOf( SpecialMobs.toString( regKey ) ) ); } tag.put( TAG_STICKY_IMMUNE, stickyBlocksTag ); final ListNBT potionsTag = new ListNBT(); - for( String potionName : immuneToPotions ) { - potionsTag.add( StringNBT.valueOf( potionName ) ); + for( Effect effect : immuneToPotions ) { + final ResourceLocation regKey = ForgeRegistries.POTIONS.getKey( effect ); + if( regKey != null ) potionsTag.add( StringNBT.valueOf( SpecialMobs.toString( regKey ) ) ); } tag.put( TAG_POTION_IMMUNE, potionsTag ); + + // Ranged attack stats (optional) + if( getRangedAttackDamage() >= 0.0F ) + tag.putFloat( TAG_ARROW_DAMAGE, getRangedAttackDamage() ); + if( getRangedAttackSpread() >= 0.0F ) + tag.putFloat( TAG_ARROW_SPREAD, getRangedAttackSpread() ); + if( getRangedWalkSpeed() >= 0.0F ) + tag.putFloat( TAG_ARROW_WALK_SPEED, getRangedWalkSpeed() ); + if( getRangedAttackCooldown() >= 0 ) + tag.putShort( TAG_ARROW_REFIRE_MIN, (short) getRangedAttackCooldown() ); + if( getRangedAttackMaxCooldown() >= 0 ) + tag.putShort( TAG_ARROW_REFIRE_MAX, (short) getRangedAttackMaxCooldown() ); + if( getRangedAttackMaxRange() >= 0.0F ) + tag.putFloat( TAG_ARROW_RANGE, getRangedAttackMaxRange() ); } /** @@ -450,12 +482,6 @@ public class SpecialMobData> { if( tag.contains( TAG_RENDER_SCALE, NBT_TYPE_NUMERICAL ) ) { setRenderScale( tag.getFloat( TAG_RENDER_SCALE ) ); } - if( tag.contains( TAG_EXPERIENCE, NBT_TYPE_NUMERICAL ) ) { - theEntity.setExperience( tag.getInt( TAG_EXPERIENCE ) ); - } - if( tag.contains( TAG_REGENERATION, NBT_TYPE_NUMERICAL ) ) { - healTimeMax = tag.getByte( TAG_REGENERATION ); - } try { if( tag.contains( TAG_TEXTURE, NBT_TYPE_STRING ) ) { @@ -472,27 +498,13 @@ public class SpecialMobData> { SpecialMobs.LOG.warn( "Failed to load textures from NBT! " + theEntity.toString() ); } - // Arrow AI - if( tag.contains( TAG_ARROW_DAMAGE, NBT_TYPE_NUMERICAL ) ) { - rangedAttackDamage = tag.getFloat( TAG_ARROW_DAMAGE ); + // Capabilities + if( tag.contains( TAG_EXPERIENCE, NBT_TYPE_NUMERICAL ) ) { + theEntity.setExperience( tag.getInt( TAG_EXPERIENCE ) ); } - if( tag.contains( TAG_ARROW_SPREAD, NBT_TYPE_NUMERICAL ) ) { - rangedAttackSpread = tag.getFloat( TAG_ARROW_SPREAD ); + if( tag.contains( TAG_REGENERATION, NBT_TYPE_NUMERICAL ) ) { + healTimeMax = tag.getByte( TAG_REGENERATION ); } - if( tag.contains( TAG_ARROW_WALK_SPEED, NBT_TYPE_NUMERICAL ) ) { - rangedWalkSpeed = tag.getFloat( TAG_ARROW_WALK_SPEED ); - } - if( tag.contains( TAG_ARROW_REFIRE_MIN, NBT_TYPE_NUMERICAL ) ) { - rangedAttackCooldown = tag.getShort( TAG_ARROW_REFIRE_MIN ); - } - if( tag.contains( TAG_ARROW_REFIRE_MAX, NBT_TYPE_NUMERICAL ) ) { - rangedAttackMaxCooldown = tag.getShort( TAG_ARROW_REFIRE_MAX ); - } - if( tag.contains( TAG_ARROW_RANGE, NBT_TYPE_NUMERICAL ) ) { - rangedAttackMaxRange = tag.getFloat( TAG_ARROW_RANGE ); - } - - // Abilities if( tag.contains( TAG_FALL_MULTI, NBT_TYPE_NUMERICAL ) ) { setFallDamageMultiplier( tag.getFloat( TAG_FALL_MULTI ) ); } @@ -502,12 +514,6 @@ public class SpecialMobData> { if( tag.contains( TAG_BURN_IMMUNE, NBT_TYPE_NUMERICAL ) ) { setImmuneToBurning( tag.getBoolean( TAG_BURN_IMMUNE ) ); } - if( tag.contains( TAG_LEASHABLE, NBT_TYPE_NUMERICAL ) ) { - setAllowLeashing( tag.getBoolean( TAG_LEASHABLE ) ); - } - if( tag.contains( TAG_TRAP_IMMUNE, NBT_TYPE_NUMERICAL ) ) { - setIgnorePressurePlates( tag.getBoolean( TAG_TRAP_IMMUNE ) ); - } if( tag.contains( TAG_DROWN_IMMUNE, NBT_TYPE_NUMERICAL ) ) { setCanBreatheInWater( tag.getBoolean( TAG_DROWN_IMMUNE ) ); } @@ -517,19 +523,49 @@ public class SpecialMobData> { if( tag.contains( TAG_WATER_DAMAGE, NBT_TYPE_NUMERICAL ) ) { setDamagedByWater( tag.getBoolean( TAG_WATER_DAMAGE ) ); } + if( tag.contains( TAG_LEASHABLE, NBT_TYPE_NUMERICAL ) ) { + setAllowLeashing( tag.getBoolean( TAG_LEASHABLE ) ); + } + if( tag.contains( TAG_TRAP_IMMUNE, NBT_TYPE_NUMERICAL ) ) { + setIgnorePressurePlates( tag.getBoolean( TAG_TRAP_IMMUNE ) ); + } if( tag.contains( TAG_STICKY_IMMUNE, NBT_TYPE_LIST ) ) { final ListNBT stickyBlocksTag = tag.getList( TAG_STICKY_IMMUNE, NBT_TYPE_STRING ); immuneToStickyBlocks.clear(); for( int i = 0; i < stickyBlocksTag.size(); i++ ) { - immuneToStickyBlocks.add( stickyBlocksTag.getString( i ) ); + final Block block = ForgeRegistries.BLOCKS.getValue( new ResourceLocation( stickyBlocksTag.getString( i ) ) ); + if( block != null && !block.is( Blocks.AIR ) ) + immuneToStickyBlocks.add( block ); } } if( tag.contains( TAG_POTION_IMMUNE, NBT_TYPE_LIST ) ) { final ListNBT potionsTag = tag.getList( TAG_POTION_IMMUNE, NBT_TYPE_STRING ); immuneToPotions.clear(); for( int i = 0; i < potionsTag.size(); i++ ) { - immuneToPotions.add( potionsTag.getString( i ) ); + final Effect effect = ForgeRegistries.POTIONS.getValue( new ResourceLocation( potionsTag.getString( i ) ) ); + if( effect != null ) + immuneToPotions.add( effect ); } } + + // Ranged attack stats + if( tag.contains( TAG_ARROW_DAMAGE, NBT_TYPE_NUMERICAL ) ) { + setRangedAttackDamage( tag.getFloat( TAG_ARROW_DAMAGE ) ); + } + if( tag.contains( TAG_ARROW_SPREAD, NBT_TYPE_NUMERICAL ) ) { + setRangedAttackSpread( tag.getFloat( TAG_ARROW_SPREAD ) ); + } + if( tag.contains( TAG_ARROW_WALK_SPEED, NBT_TYPE_NUMERICAL ) ) { + setRangedWalkSpeed( tag.getFloat( TAG_ARROW_WALK_SPEED ) ); + } + if( tag.contains( TAG_ARROW_REFIRE_MIN, NBT_TYPE_NUMERICAL ) ) { + setRangedAttackCooldown( tag.getShort( TAG_ARROW_REFIRE_MIN ) ); + } + if( tag.contains( TAG_ARROW_REFIRE_MAX, NBT_TYPE_NUMERICAL ) ) { + setRangedAttackMaxCooldown( tag.getShort( TAG_ARROW_REFIRE_MAX ) ); + } + if( tag.contains( TAG_ARROW_RANGE, NBT_TYPE_NUMERICAL ) ) { + setRangedAttackMaxRange( tag.getFloat( TAG_ARROW_RANGE ) ); + } } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/IExplodingMob.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/IExplodingMob.java new file mode 100644 index 0000000..479a8c5 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/IExplodingMob.java @@ -0,0 +1,12 @@ +package fathertoast.specialmobs.common.entity.ai; + +public interface IExplodingMob { + /** Sets this exploding entity's swell direction. */ + void setSwellDir( int value ); + + /** @return This exploding entity's swell direction. */ + int getSwellDir(); + + /** @return Additional range from its target at which this entity will start to explode. */ + default double getExtraRange() { return 0.0; } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/ChargeCreeperGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/ChargeCreeperGoal.java index e04e289..6c85fb3 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/ChargeCreeperGoal.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/ChargeCreeperGoal.java @@ -1,6 +1,6 @@ package fathertoast.specialmobs.common.entity.ai.goal; -import fathertoast.specialmobs.common.entity.creeper._SpecialCreeperEntity; +import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.zombie.MadScientistZombieEntity; import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.monster.CreeperEntity; @@ -85,12 +85,7 @@ public class ChargeCreeperGoal extends Goal madman.getLookControl().setLookAt( this.creeper.getX(), this.creeper.getEyeY(), this.creeper.getZ() ); if( madman.distanceTo( creeper ) < 1.5D ) { - creeper.getEntityData().set( CreeperEntity.DATA_IS_POWERED, true ); - - // HEE HEE HEE HAW - if( creeper instanceof _SpecialCreeperEntity && creeper.level.random.nextDouble() < 0.1 ) { // TODO config - ((_SpecialCreeperEntity) creeper).setSupercharged( true ); - } + MobHelper.charge( creeper ); madman.level.playSound( null, creeper.getX() + 0.5D, creeper.getY(), creeper.getZ() + 0.5D, SoundEvents.BEE_STING, SoundCategory.HOSTILE, 0.9F, 1.0F ); creeper = null; } diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialBlazeAttackGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialBlazeAttackGoal.java index c171cf3..94aec75 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialBlazeAttackGoal.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialBlazeAttackGoal.java @@ -58,7 +58,7 @@ public class SpecialBlazeAttackGoal extends Goal { else lastSeen++; final double distanceSqr = blaze.distanceToSqr( target ); - final float rangeSq = data.rangedAttackMaxRange * data.rangedAttackMaxRange; + final float rangeSq = data.getRangedAttackMaxRange() * data.getRangedAttackMaxRange(); if( distanceSqr < getAttackReachSqr( target ) ) { if( canSee && attackTime <= 0 ) { attackTime = 20; @@ -71,14 +71,14 @@ public class SpecialBlazeAttackGoal extends Goal { attackStep++; if( attackStep == 1 ) { - attackTime = data.rangedAttackMaxCooldown - data.rangedAttackCooldown; + attackTime = data.getRangedAttackCooldown(); blaze.setCharged( true ); } else if( attackStep <= 1 + blaze.fireballBurstCount ) { attackTime = blaze.fireballBurstDelay; } else { - attackTime = data.rangedAttackCooldown; + attackTime = data.getRangedAttackMaxCooldown() - data.getRangedAttackCooldown(); attackStep = 0; blaze.setCharged( false ); } diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastFireballAttackGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastFireballAttackGoal.java index 354f1dc..f311a74 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastFireballAttackGoal.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastFireballAttackGoal.java @@ -38,19 +38,19 @@ public class SpecialGhastFireballAttackGoal extends Goal { final SpecialMobData<_SpecialGhastEntity> data = ghast.getSpecialData(); - if( target.distanceToSqr( ghast ) < data.rangedAttackMaxRange * data.rangedAttackMaxRange && ghast.canSee( target ) ) { + if( target.distanceToSqr( ghast ) < data.getRangedAttackMaxRange() * data.getRangedAttackMaxRange() && ghast.canSee( target ) ) { chargeTime++; - if( chargeTime == (data.rangedAttackCooldown >> 1) && !ghast.isSilent() ) { + if( chargeTime == (data.getRangedAttackCooldown() >> 1) && !ghast.isSilent() ) { ghast.level.levelEvent( null, References.EVENT_GHAST_WARN, ghast.blockPosition(), 0 ); } - if( chargeTime >= data.rangedAttackCooldown ) { + if( chargeTime >= data.getRangedAttackCooldown() ) { ghast.performRangedAttack( target, 1.0F ); - chargeTime = data.rangedAttackCooldown - data.rangedAttackMaxCooldown; + chargeTime = data.getRangedAttackCooldown() - data.getRangedAttackMaxCooldown(); } } else if( chargeTime > 0 ) { chargeTime--; } - ghast.setCharging( chargeTime > (data.rangedAttackCooldown >> 1) ); + ghast.setCharging( chargeTime > (data.getRangedAttackCooldown() >> 1) ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastLookAroundGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastLookAroundGoal.java index 61673a0..120eb9b 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastLookAroundGoal.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialGhastLookAroundGoal.java @@ -28,8 +28,8 @@ public class SpecialGhastLookAroundGoal extends Goal { public void tick() { final LivingEntity target = ghast.getTarget(); if( target != null ) { - final float range = ghast.getSpecialData().rangedAttackMaxRange > 0.0F ? - ghast.getSpecialData().rangedAttackMaxRange : + final float range = ghast.getSpecialData().getRangedAttackMaxRange() > 0.0F ? + ghast.getSpecialData().getRangedAttackMaxRange() : 16.0F; // Range for melee ghast to face target if( target.distanceToSqr( ghast ) < range * range ) { diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialSwellGoal.java b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialSwellGoal.java new file mode 100644 index 0000000..e285fd1 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/ai/goal/SpecialSwellGoal.java @@ -0,0 +1,49 @@ +package fathertoast.specialmobs.common.entity.ai.goal; + +import fathertoast.specialmobs.common.entity.ai.IExplodingMob; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MobEntity; +import net.minecraft.entity.ai.goal.Goal; + +import java.util.EnumSet; + +/** + * The "creeper swell" goal repurposed for use on other mobs. + *

+ * {@link net.minecraft.entity.ai.goal.CreeperSwellGoal} + */ +public class SpecialSwellGoal extends Goal { + + private final T mob; + + private LivingEntity target; + + public SpecialSwellGoal( T entity ) { + mob = entity; + setFlags( EnumSet.of( Flag.MOVE ) ); + } + + public boolean canUse() { + final LivingEntity target = mob.getTarget(); + return mob.getSwellDir() > 0 || target != null && mob.distanceToSqr( target ) < 9.0F + mob.getExtraRange(); + } + + public void start() { + mob.getNavigation().stop(); + target = mob.getTarget(); + } + + public void stop() { + mob.setSwellDir( -1 ); + target = null; + } + + public void tick() { + if( target == null || mob.distanceToSqr( target ) > 49.0 || !mob.getSensing().canSee( target ) ) { + mob.setSwellDir( -1 ); + } + else { + mob.setSwellDir( 1 ); + } + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/CinderBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/CinderBlazeEntity.java index e889568..f8864c2 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/CinderBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/CinderBlazeEntity.java @@ -3,14 +3,11 @@ package fathertoast.specialmobs.common.entity.blaze; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -28,17 +25,12 @@ public class CinderBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.5F, 0.9F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.DISABLED ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.ATTACK_DAMAGE, -2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.DISABLED ) + .size( 0.5F, 0.5F, 0.9F ) + .experience( 2 ).disableRangedAttack() + .addToAttribute( Attributes.ATTACK_DAMAGE, -2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -55,23 +47,18 @@ public class CinderBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return CinderBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public CinderBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.5F ); - xpReward = 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage -= 1.0F; - disableRangedAI(); - } + public CinderBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { target.setSecondsOnFire( 4 ); } diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/ConflagrationBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/ConflagrationBlazeEntity.java index aff3e7a..2fb59b1 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/ConflagrationBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/ConflagrationBlazeEntity.java @@ -20,7 +20,7 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -37,9 +37,11 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.7F ); - return new BestiaryInfo( 0xFFF87E, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureBaseOnly() + .size( 1.5F, 0.9F, 2.7F ) + .addExperience( 4 ); } @SpecialMob.LanguageProvider @@ -58,6 +60,11 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return ConflagrationBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -68,13 +75,10 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { /** The level of increased attack damage gained. */ private int growthLevel; - public ConflagrationBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - xpReward += 4; - } + public ConflagrationBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { if( target instanceof LivingEntity ) { MobHelper.stealLife( this, (LivingEntity) target, 2.0F ); @@ -91,12 +95,6 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { if( !level.isClientSide() && growthLevel < 7 ) { growthLevel++; - - getSpecialData().rangedAttackDamage += 0.5F; - getSpecialData().rangedAttackCooldown -= 4; - getSpecialData().rangedAttackMaxCooldown -= 4; - if( growthLevel == 7 ) fireballBurstCount++; - updateFeedingLevels(); } amount /= 2.0F; @@ -107,6 +105,13 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { /** Recalculates the modifiers associated with this entity's feeding level counters. */ private void updateFeedingLevels() { if( level != null && !level.isClientSide ) { + final int cooldownReduction = MathHelper.floor( getConfig().GENERAL.rangedAttackCooldown.get() * growthLevel * 0.1 ); + getSpecialData().setRangedAttackCooldown( getConfig().GENERAL.rangedAttackCooldown.get() - cooldownReduction ); + getSpecialData().setRangedAttackMaxCooldown( getConfig().GENERAL.rangedAttackMaxCooldown.get() - cooldownReduction ); + + fireballBurstCount = getConfig().BLAZES.fireballBurstCount.get(); + if( growthLevel >= 7 ) fireballBurstCount++; + final ModifiableAttributeInstance damage = getAttribute( Attributes.ATTACK_DAMAGE ); //noinspection ConstantConditions damage.removeModifier( DAMAGE_BOOST.getId() ); @@ -130,12 +135,4 @@ public class ConflagrationBlazeEntity extends _SpecialBlazeEntity { growthLevel = saveTag.getByte( References.TAG_GROWTH_LEVEL ); updateFeedingLevels(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "conflagration" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/EmberBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/EmberBlazeEntity.java index 64a58c9..72a1ca7 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/EmberBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/EmberBlazeEntity.java @@ -4,17 +4,14 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,17 +27,12 @@ public class EmberBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -58,32 +50,21 @@ public class EmberBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return EmberBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public EmberBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - disableRangedAI(); - } + public EmberBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { if( target instanceof LivingEntity ) { MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "ember" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/HellfireBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/HellfireBlazeEntity.java index e83878d..8c5ba09 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/HellfireBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/HellfireBlazeEntity.java @@ -3,18 +3,17 @@ package fathertoast.specialmobs.common.entity.blaze; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.BlazeSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.FireballEntity; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -31,16 +30,18 @@ public class HellfireBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.7F, 1.99F ); - return new BestiaryInfo( 0xDDDDDD ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDDDDDD ) + .uniqueTextureBaseOnly() + .size( 1.1F, 0.7F, 1.99F ) + .addExperience( 2 ) + .fireballAttack( 0.05, 60, 100, 40.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new BlazeSpeciesConfig( species, 1, 0 ); } @SpecialMob.LanguageProvider @@ -58,31 +59,25 @@ public class HellfireBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HellfireBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- /** The base explosion strength of this blaze's fireballs. */ private int explosionPower = 2; - public HellfireBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.1F ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 0.05F; - setRangedAI( 1, 0, 60, 100, 40.0F ); - } + public HellfireBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 ); - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance; final double dY = target.getY( 0.5 ) - getY( 0.5 ); final double dZ = target.getZ() - getZ() + getRandom().nextGaussian() * accelVariance; @@ -105,12 +100,4 @@ public class HellfireBlazeEntity extends _SpecialBlazeEntity { if( saveTag.contains( References.TAG_EXPLOSION_POWER, References.NBT_TYPE_NUMERICAL ) ) explosionPower = saveTag.getByte( References.TAG_EXPLOSION_POWER ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "hellfire" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/InfernoBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/InfernoBlazeEntity.java index a251cc2..a61b002 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/InfernoBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/InfernoBlazeEntity.java @@ -3,18 +3,17 @@ package fathertoast.specialmobs.common.entity.blaze; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.BlazeSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,15 +29,17 @@ public class InfernoBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xF14F00 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xF14F00 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ) + .fireballAttack( 3.0, 80, 100, 20.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new BlazeSpeciesConfig( species, 12, 2 ); } @SpecialMob.LanguageProvider @@ -57,33 +58,21 @@ public class InfernoBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return InfernoBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public InfernoBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 3.0F; - setRangedAI( 12, 2, 80, 100, 20.0F ); - } + public InfernoBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { if( target instanceof LivingEntity ) { MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "inferno" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/JoltBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/JoltBlazeEntity.java index bfd3bcd..62b28ae 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/JoltBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/JoltBlazeEntity.java @@ -4,7 +4,6 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; @@ -13,7 +12,6 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.effect.LightningBoltEntity; import net.minecraft.item.Items; @@ -21,7 +19,6 @@ import net.minecraft.tags.FluidTags; import net.minecraft.util.DamageSource; import net.minecraft.util.Direction; import net.minecraft.util.IndirectEntityDamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -42,17 +39,12 @@ public class JoltBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x499CAE ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x499CAE ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -70,21 +62,18 @@ public class JoltBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return JoltBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public JoltBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - disableRangedAI(); - } + public JoltBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { if( target instanceof LivingEntity ) { MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F ); @@ -129,6 +118,10 @@ public class JoltBlazeEntity extends _SpecialBlazeEntity { return success; } + /** Called when this entity is struck by lightning. */ + @Override + public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) { } + /** @return Teleports this "enderman" to a random nearby position; returns true if successful. */ protected boolean teleport() { if( level.isClientSide() || !isAlive() ) return false; @@ -174,16 +167,4 @@ public class JoltBlazeEntity extends _SpecialBlazeEntity { } return success; } - - /** Called when this entity is struck by lightning. */ - @Override - public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) { } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "jolt" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/WildfireBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/WildfireBlazeEntity.java index 1c0fe85..4d91677 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/WildfireBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/WildfireBlazeEntity.java @@ -3,16 +3,15 @@ package fathertoast.specialmobs.common.entity.blaze; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.WildfireBlazeSpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -30,16 +29,19 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.7F ); - return new BestiaryInfo( 0xF4EE32 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xF4EE32 ) + .uniqueTextureBaseOnly() + .size( 1.5F, 0.9F, 2.7F ) + .addExperience( 2 ).regen( 40 ) + .fireballAttack( 0.1, 30, 50, 20.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialBlazeEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new WildfireBlazeSpeciesConfig( species, 1, 0, + 3, 6, 4, 10 ); } @SpecialMob.LanguageProvider @@ -58,6 +60,11 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WildfireBlazeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -68,22 +75,16 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity { public WildfireBlazeEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - getSpecialData().setRegenerationTime( 40 ); - xpReward += 2; - - babies = 3 + random.nextInt( 4 ); - summons = 4 + random.nextInt( 7 ); + babies = getConfig().WILDFIRE.babies.next( random ); + summons = getConfig().WILDFIRE.summons.next( random ); } - /** Override to change this entity's AI goals. */ + /** @return This entity's species config. */ @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 0.1F; - setRangedAI( 1, 0, 30, 50, 20.0F ); - } + public WildfireBlazeSpeciesConfig getConfig() { return (WildfireBlazeSpeciesConfig) getSpecies().config; } /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override protected void onVariantAttack( Entity target ) { target.setSecondsOnFire( 8 ); } @@ -157,12 +158,4 @@ public class WildfireBlazeEntity extends _SpecialBlazeEntity { if( saveTag.contains( References.TAG_SUMMONS, References.NBT_TYPE_NUMERICAL ) ) summons = saveTag.getByte( References.TAG_SUMMONS ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "wildfire" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/blaze/_SpecialBlazeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/blaze/_SpecialBlazeEntity.java index d73addc..c0257ea 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/blaze/_SpecialBlazeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/blaze/_SpecialBlazeEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.blaze; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.BlazeSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.entity.ai.AIHelper; @@ -25,14 +26,10 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.IServerWorld; import net.minecraft.world.World; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @@ -46,15 +43,24 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob public static MobFamily.Species<_SpecialBlazeEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFFF87E ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ) + .vanillaTextureBaseOnly( "textures/entity/blaze.png" ) + .experience( 10 ).fireImmune().waterSensitive() + .fireballAttack( 1.0, 60, 100, 48.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return BlazeEntity.createAttributes(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new BlazeSpeciesConfig( species, 3, 6 ); } + /** @return This entity's species config. */ + public BlazeSpeciesConfig getConfig() { return (BlazeSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return BlazeEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Blaze", @@ -72,12 +78,6 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob //--------------- Variant-Specific Breakouts ---------------- - public _SpecialBlazeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - getSpecialData().setDamagedByWater( true ); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -86,29 +86,12 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob goalSelector.addGoal( 4, new SpecialBlazeAttackGoal( this ) ); AIHelper.replaceHurtByTarget( this, new SpecialHurtByTargetGoal( this, BlazeEntity.class ).setAlertOthers() ); - getSpecialData().rangedAttackDamage = 2.0F; - setRangedAI( 3, 6, 60, 100, 48.0F ); registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { - setRangedAI( 0, 6, 60, 100, 0.0F ); - } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( int burstCount, int burstDelay, int chargeTime, int cooldownTime, float range ) { - fireballBurstCount = burstCount; - fireballBurstDelay = burstDelay; - - getSpecialData().rangedAttackCooldown = cooldownTime; - getSpecialData().rangedAttackMaxCooldown = cooldownTime + chargeTime; - getSpecialData().rangedAttackMaxRange = range; - } - /** Called when this entity successfully damages a target to apply on-hit effects. */ @Override public void doEnchantDamageEffects( LivingEntity attacker, Entity target ) { @@ -119,6 +102,21 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob /** Override to apply effects when this entity hits a target with a melee attack. */ protected void onVariantAttack( Entity target ) { } + /** Called to attack the target with a ranged attack. */ + @Override + public void performRangedAttack( LivingEntity target, float damageMulti ) { + if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 ); + + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); + final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance; + final double dY = target.getY( 0.5 ) - getY( 0.5 ); + final double dZ = target.getZ() - getZ() + getRandom().nextGaussian() * accelVariance; + + final SmallFireballEntity fireball = new SmallFireballEntity( level, this, dX, dY, dZ ); + fireball.setPos( getX(), getY( 0.5 ) + 0.5, getZ() ); + level.addFreshEntity( fireball ); + } + /** Override to save data to this entity's NBT data. */ public void addVariantSaveData( CompoundNBT saveTag ) { } @@ -136,35 +134,19 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob /** The ticks between each shot in a burst. */ public int fireballBurstDelay; + public _SpecialBlazeEntity( EntityType entityType, World world ) { + super( entityType, world ); + fireballBurstCount = getConfig().BLAZES.fireballBurstCount.get(); + fireballBurstDelay = getConfig().BLAZES.fireballBurstDelay.get(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); - } - - /** Called to attack the target with a ranged attack. */ - @Override - public void performRangedAttack( LivingEntity target, float damageMulti ) { - if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 ); - - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; - final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance; - final double dY = target.getY( 0.5 ) - getY( 0.5 ); - final double dZ = target.getZ() - getZ() + getRandom().nextGaussian() * accelVariance; - - final SmallFireballEntity fireball = new SmallFireballEntity( level, this, dX, dY, dZ ); - fireball.setPos( getX(), getY( 0.5 ) + 0.5, getZ() ); - level.addFreshEntity( fireball ); - } - - /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ - @Nullable - public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, - @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { - groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - // TODO ranged attack - return groupData; + specialData = new SpecialMobData<>( this, SCALE ); } @@ -174,7 +156,12 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob /** @return This mob's special data. */ @Override - public SpecialMobData<_SpecialBlazeEntity> getSpecialData() { return specialData; } + public final SpecialMobData<_SpecialBlazeEntity> getSpecialData() { return specialData; } + + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } /** @return The experience that should be dropped by this entity. */ @Override @@ -184,16 +171,6 @@ public class _SpecialBlazeEntity extends BlazeEntity implements IRangedAttackMob @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "blaze/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/blaze.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java index c79021b..10ce21a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.cavespider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,18 +24,13 @@ public class BabyCaveSpiderEntity extends _SpecialCaveSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.6F, 0.4F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.DISABLED ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) - .multAttribute( Attributes.MAX_HEALTH, 1.0 / 3.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.DISABLED ) + .size( 0.4F, 0.6F, 0.4F ) + .experience( 1 ).disableRangedAttack() + .multiplyAttribute( Attributes.MAX_HEALTH, 0.33 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -55,21 +47,13 @@ public class BabyCaveSpiderEntity extends _SpecialCaveSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BabyCaveSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BabyCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.4F ); - getSpecialData().rangedAttackDamage -= 1.0F; - getSpecialData().rangedAttackMaxRange = 0.0F; - xpReward = 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage -= 1.0F; - getSpecialData().rangedAttackMaxRange = 0.0F; - } + public BabyCaveSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/FlyingCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/FlyingCaveSpiderEntity.java index b95b155..3f3b95f 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/FlyingCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/FlyingCaveSpiderEntity.java @@ -4,16 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.ai.goal.SpecialLeapAtTargetGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,16 +25,11 @@ public class FlyingCaveSpiderEntity extends _SpecialCaveSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x6388B2 ); - //TODO theme - mountain - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x6388B2 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureWithEyes() + .addExperience( 2 ).fallImmune().disableRangedAttack() + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -56,30 +47,20 @@ public class FlyingCaveSpiderEntity extends _SpecialCaveSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FlyingCaveSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FlyingCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - xpReward += 2; - } + public FlyingCaveSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackMaxRange = 0.0F; - goalSelector.addGoal( 3, new SpecialLeapAtTargetGoal( this, 10, 6.0F, 12.0F, 2.0F, 2.0F ) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "flying" ), - GET_TEXTURE_PATH( "flying_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/MotherCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/MotherCaveSpiderEntity.java index 853f095..ba0c7ce 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/MotherCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/MotherCaveSpiderEntity.java @@ -3,20 +3,18 @@ package fathertoast.specialmobs.common.entity.cavespider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.MotherSpiderSpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.ILivingEntityData; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -35,20 +33,25 @@ public class MotherCaveSpiderEntity extends _SpecialCaveSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 0.6F ); - return new BestiaryInfo( 0xB300B3 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xB300B3 ) + .uniqueTextureWithEyes() + .size( 0.8F, 0.9F, 0.6F ) + .addExperience( 1 ).regen( 30 ) + .addToAttribute( Attributes.MAX_HEALTH, 16.0 ).addToAttribute( Attributes.ARMOR, 6.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 3.0 ).addToRangedDamage( 1.5 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 16.0 ) - .addAttribute( Attributes.ARMOR, 6.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 3.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new MotherSpiderSpeciesConfig( species, DEFAULT_SPIT_CHANCE, + 2, 4, 2, 4 ); } + /** @return This entity's species config. */ + @Override + public MotherSpiderSpeciesConfig getConfig() { return (MotherSpiderSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Mother Cave Spider", @@ -64,28 +67,23 @@ public class MotherCaveSpiderEntity extends _SpecialCaveSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MotherCaveSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public MotherCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.8F ); - getSpecialData().setRegenerationTime( 30 ); - xpReward += 1; - - babies = 2 + random.nextInt( 3 ); - extraBabies = 2 + random.nextInt( 3 ); - } - /** The number of babies spawned on death. */ private int babies; /** The number of extra babies that can be spawned from hits. */ private int extraBabies; - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 1.5F; + public MotherCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + babies = getConfig().MOTHER.babies.next( random ); + extraBabies = getConfig().MOTHER.extraBabies.next( random ); } /** @return Attempts to damage this entity; returns true if the hit was successful. */ @@ -159,13 +157,4 @@ public class MotherCaveSpiderEntity extends _SpecialCaveSpiderEntity { if( saveTag.contains( References.TAG_EXTRA_BABIES, References.NBT_TYPE_NUMERICAL ) ) extraBabies = saveTag.getByte( References.TAG_EXTRA_BABIES ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "mother" ), - GET_TEXTURE_PATH( "mother_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WebCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WebCaveSpiderEntity.java index 8215531..2fc6f8d 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WebCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WebCaveSpiderEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.cavespider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.WebSpiderSpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -11,12 +12,10 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.monster.SpiderEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -33,19 +32,24 @@ public class WebCaveSpiderEntity extends _SpecialCaveSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xE7E7E7, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE7E7E7 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .spitAttackMultiplied( 0.1, 1.0, 2.0F, 1.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new WebSpiderSpeciesConfig( species, 0.01, 2, 6 ); } + /** @return This entity's species config. */ + @Override + public WebSpiderSpeciesConfig getConfig() { return (WebSpiderSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Cave Weaver", @@ -61,18 +65,22 @@ public class WebCaveSpiderEntity extends _SpecialCaveSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WebCaveSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public WebCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - webCount = 2 + random.nextInt( 5 ); - } - /** The number of cobwebs this spider can place. */ private int webCount; + public WebCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + webCount = getConfig().WEB.webCount.next( random ); + } + /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -113,13 +121,4 @@ public class WebCaveSpiderEntity extends _SpecialCaveSpiderEntity { if( saveTag.contains( References.TAG_AMMO, References.NBT_TYPE_NUMERICAL ) ) webCount = saveTag.getByte( References.TAG_AMMO ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "web" ), - GET_TEXTURE_PATH( "web_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WitchCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WitchCaveSpiderEntity.java index fca535f..a52b7ab 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WitchCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WitchCaveSpiderEntity.java @@ -4,18 +4,15 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.EffectType; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -31,16 +28,12 @@ public class WitchCaveSpiderEntity extends _SpecialCaveSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDD0E0E, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - forest - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) - .addAttribute( Attributes.ARMOR, 15.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDD0E0E ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .spitAttackMultiplied( 0.1, 1.0, 2.0F, 1.0 ) + .addToAttribute( Attributes.ARMOR, 15.0 ); } @SpecialMob.LanguageProvider @@ -58,13 +51,15 @@ public class WitchCaveSpiderEntity extends _SpecialCaveSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WitchCaveSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public WitchCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public WitchCaveSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -81,13 +76,4 @@ public class WitchCaveSpiderEntity extends _SpecialCaveSpiderEntity { // Witch spider is immune to debuffs return effect.getEffect().getCategory() != EffectType.HARMFUL && super.canBeAffected( effect ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "witch" ), - GET_TEXTURE_PATH( "witch_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/_SpecialCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/_SpecialCaveSpiderEntity.java index f7fc739..338e4e0 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/_SpecialCaveSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/_SpecialCaveSpiderEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.cavespider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpiderSpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.util.References; @@ -21,13 +22,9 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.IServerWorld; import net.minecraft.world.World; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @@ -41,15 +38,26 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci public static MobFamily.Species<_SpecialCaveSpiderEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xA80E0E ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA80E0E ).familySize( 0.7F ) + .vanillaTextureWithEyes( "textures/entity/spider/cave_spider.png", "textures/entity/spider_eyes.png" ) + .experience( 5 ).spider() + .spitAttack( 1.0, 1.3, 40, 40, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return CaveSpiderEntity.createAttributes(); + protected static final double DEFAULT_SPIT_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SpiderSpeciesConfig( species, DEFAULT_SPIT_CHANCE ); } + /** @return This entity's species config. */ + public SpiderSpeciesConfig getConfig() { return (SpiderSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return CaveSpiderEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Cave Spider", @@ -67,21 +75,10 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci //--------------- Variant-Specific Breakouts ---------------- - public _SpecialCaveSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); - - getSpecialData().rangedAttackDamage = 1.0F; - getSpecialData().rangedAttackSpread = 1.3F; - getSpecialData().rangedAttackCooldown = 40; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 10.0F; registerVariantGoals(); } @@ -110,20 +107,18 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialCaveSpiderEntity.class, DataSerializers.FLOAT ); + public _SpecialCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + if( !getConfig().SPIDERS.spitterChance.rollChance( random ) ) getSpecialData().disableRangedAttack(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 0.7F ); - } - - /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ - @Nullable - public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, - @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { - groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - // TODO ranged attack - return groupData; + specialData = new SpecialMobData<>( this, SCALE ); } @@ -133,7 +128,12 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci /** @return This mob's special data. */ @Override - public SpecialMobData<_SpecialCaveSpiderEntity> getSpecialData() { return specialData; } + public final SpecialMobData<_SpecialCaveSpiderEntity> getSpecialData() { return specialData; } + + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } /** @return The experience that should be dropped by this entity. */ @Override @@ -143,19 +143,6 @@ public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpeci @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "cavespider/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/spider/cave_spider.png" ), - new ResourceLocation( "textures/entity/spider_eyes.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DarkCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DarkCreeperEntity.java index cad8fb7..4ffb983 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DarkCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DarkCreeperEntity.java @@ -10,14 +10,12 @@ import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; @@ -36,8 +34,10 @@ public class DarkCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xF9FF3A ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xF9FF3A ) + .uniqueTextureWithEyes() + .addExperience( 1 ); } @SpecialMob.LanguageProvider @@ -56,13 +56,15 @@ public class DarkCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DarkCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DarkCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public DarkCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius / 2.0F ); } @@ -121,13 +123,4 @@ public class DarkCreeperEntity extends _SpecialCreeperEntity { protected void modifyVariantLingeringCloudEffects( List potions ) { potions.add( new EffectInstance( Effects.BLINDNESS, 100 ) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "dark" ), - GET_TEXTURE_PATH( "dark_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DeathCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DeathCreeperEntity.java index d9b620e..2645049 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DeathCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DeathCreeperEntity.java @@ -3,17 +3,15 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.CreeperSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,16 +27,17 @@ public class DeathCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.6F ); - return new BestiaryInfo( 0xCD0000 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xCD0000 ) + .uniqueTextureWithEyes() + .size( 1.5F, 0.9F, 2.6F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new CreeperSpeciesConfig( species, false, true, false ); } @SpecialMob.LanguageProvider @@ -57,25 +56,16 @@ public class DeathCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DeathCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DeathCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - setExplodesWhileBurning( true ); - xpReward += 2; - } + public DeathCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius + 1.0F ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "death" ), - GET_TEXTURE_PATH( "death_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DirtCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DirtCreeperEntity.java index 45629ec..d86bd7a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DirtCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DirtCreeperEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; @@ -11,11 +10,8 @@ import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Explosion; import net.minecraft.world.World; @@ -33,15 +29,11 @@ public class DirtCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x78553B ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.ARMOR, 6.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x78553B ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).burnImmune() + .addToAttribute( Attributes.ARMOR, 6.0 ); } @SpecialMob.LanguageProvider @@ -61,14 +53,15 @@ public class DirtCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DirtCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DirtCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setImmuneToBurning( true ); - xpReward += 1; - } + public DirtCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion. */ @Override @@ -97,12 +90,4 @@ public class DirtCreeperEntity extends _SpecialCreeperEntity { } } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "dirt" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DoomCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DoomCreeperEntity.java index 1f4d1b6..9f86911 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DoomCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DoomCreeperEntity.java @@ -9,10 +9,8 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.AreaEffectCloudEntity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,9 +27,10 @@ public class DoomCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x494949 ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x494949 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithOverlay() + .addExperience( 1 ).effectImmune( Effects.HARM, Effects.WITHER ); } @SpecialMob.LanguageProvider @@ -49,14 +48,15 @@ public class DoomCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DoomCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DoomCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.HARM, Effects.WITHER ); - xpReward += 1; - } + public DoomCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius / 2.0F ); } @@ -82,14 +82,4 @@ public class DoomCreeperEntity extends _SpecialCreeperEntity { protected void modifyVariantLingeringCloud( AreaEffectCloudEntity potionCloud ) { potionCloud.setRadius( (float) explosionRadius * (isPowered() ? 2.0F : 1.0F) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "doom" ), - null, - GET_TEXTURE_PATH( "doom_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DrowningCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DrowningCreeperEntity.java index 4f022e3..262f490 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/DrowningCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/DrowningCreeperEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder; @@ -13,14 +12,11 @@ import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.passive.fish.PufferfishEntity; import net.minecraft.item.Items; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tags.BlockTags; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Explosion; import net.minecraft.world.IServerWorld; @@ -39,16 +35,11 @@ public class DrowningCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x2D41F4, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - water - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x2D41F4 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.WATER ) + .uniqueTextureWithEyes() + .addExperience( 2 ).drownImmune().fluidPushImmune() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ); } @SpecialMob.LanguageProvider @@ -69,15 +60,15 @@ public class DrowningCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DrowningCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DrowningCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setCanBreatheInWater( true ); - getSpecialData().setIgnoreWaterPush( true ); - xpReward += 2; - } + public DrowningCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius ) + 3.0F; } @@ -147,7 +138,6 @@ public class DrowningCreeperEntity extends _SpecialCreeperEntity { } } - /** Helper method to simplify spawning pufferfish. */ private void spawnPufferfish( BlockPos pos ) { if( !(level instanceof IServerWorld) ) return; @@ -164,13 +154,4 @@ public class DrowningCreeperEntity extends _SpecialCreeperEntity { @Override public boolean isInWaterRainOrBubble() { return true; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "drowning" ), - GET_TEXTURE_PATH( "drowning_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/EnderCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/EnderCreeperEntity.java index c60e6dc..6c11ec6 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/EnderCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/EnderCreeperEntity.java @@ -3,15 +3,15 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.CreeperSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.entity.ai.AIHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.ai.goal.NearestAttackableTargetGoal; @@ -49,16 +49,16 @@ public class EnderCreeperEntity extends _SpecialCreeperEntity implements IAngera public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xCC00FA, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - the end + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xCC00FA ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithEyes() + .addExperience( 2 ).waterSensitive() + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new CreeperSpeciesConfig( species, true, false, false ); } @SpecialMob.LanguageProvider @@ -76,15 +76,15 @@ public class EnderCreeperEntity extends _SpecialCreeperEntity implements IAngera @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return EnderCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public EnderCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setDamagedByWater( true ); - setCannotExplodeWhileWet( true ); - xpReward += 2; - } + public EnderCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -107,15 +107,6 @@ public class EnderCreeperEntity extends _SpecialCreeperEntity implements IAngera readPersistentAngerSaveData( (ServerWorld) level, saveTag ); } - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "ender" ), - GET_TEXTURE_PATH( "ender_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- IAngerable Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/FireCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/FireCreeperEntity.java index 4cd6147..0203fd1 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/FireCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/FireCreeperEntity.java @@ -3,14 +3,14 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.CreeperSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -26,10 +26,15 @@ public class FireCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xE13916 ); - //TODO theme - fire + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE13916 ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fireImmune().waterSensitive(); + } + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new CreeperSpeciesConfig( species, true, false, false ); } @SpecialMob.LanguageProvider @@ -48,27 +53,19 @@ public class FireCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FireCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FireCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setDamagedByWater( true ); - setCannotExplodeWhileWet( true ); - xpReward += 1; - } + public FireCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion. */ @Override protected void makeVariantExplosion( float explosionPower ) { ExplosionHelper.explode( this, explosionPower, true, true ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fire" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/GravelCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/GravelCreeperEntity.java index cfeff5a..7ef4075 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/GravelCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/GravelCreeperEntity.java @@ -9,11 +9,9 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Blocks; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.item.FallingBlockEntity; import net.minecraft.item.Items; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.world.Explosion; @@ -32,8 +30,10 @@ public class GravelCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x908884 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x908884 ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).burnImmune(); } @SpecialMob.LanguageProvider @@ -52,14 +52,15 @@ public class GravelCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GravelCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public GravelCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setImmuneToBurning( true ); - xpReward += 1; - } + public GravelCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius / 2.0F ); } @@ -106,12 +107,4 @@ public class GravelCreeperEntity extends _SpecialCreeperEntity { } return super.hurt( source, amount ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "gravel" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/JumpingCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/JumpingCreeperEntity.java index b34536e..0a724d2 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/JumpingCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/JumpingCreeperEntity.java @@ -5,16 +5,12 @@ import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.ai.AIHelper; import fathertoast.specialmobs.common.entity.ai.goal.SpecialLeapAtTargetGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,16 +26,11 @@ public class JumpingCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x7D6097 ); - //TODO theme - mountain - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x7D6097 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).fallImmune() + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -57,14 +48,15 @@ public class JumpingCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return JumpingCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public JumpingCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - xpReward += 2; - } + public JumpingCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -72,12 +64,4 @@ public class JumpingCreeperEntity extends _SpecialCreeperEntity { AIHelper.insertGoal( goalSelector, 4, new SpecialLeapAtTargetGoal( this, 10, 6.0F, 10.0F, 1.3F, 2.0F ) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "jumping" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/LightningCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/LightningCreeperEntity.java index cd5af70..8bcf326 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/LightningCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/LightningCreeperEntity.java @@ -8,9 +8,7 @@ import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.world.storage.IServerWorldInfo; @@ -27,9 +25,10 @@ public class LightningCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0x499CAE ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x499CAE ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fireImmune(); } @SpecialMob.LanguageProvider @@ -47,13 +46,15 @@ public class LightningCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return LightningCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public LightningCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public LightningCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ @Override @@ -95,12 +96,4 @@ public class LightningCreeperEntity extends _SpecialCreeperEntity { } } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "lightning" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/MiniCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/MiniCreeperEntity.java index 6656531..705d043 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/MiniCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/MiniCreeperEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.world.World; @@ -26,16 +23,10 @@ public class MiniCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.5F, 0.9F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.LOW ) + .size( 0.5F, 0.5F, 0.9F ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -52,13 +43,15 @@ public class MiniCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MiniCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public MiniCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.5F ); - } + public MiniCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this creeper's explosion power multiplier. */ protected float getVariantExplosionPower( float radius ) { return super.getVariantExplosionPower( radius / 2.0F ); } diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/SkeletonCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/SkeletonCreeperEntity.java index 598ba85..8e2a0a1 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/SkeletonCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/SkeletonCreeperEntity.java @@ -4,15 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.ai.AIHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.goal.FleeSunGoal; import net.minecraft.entity.ai.goal.RestrictSunGoal; @@ -21,7 +18,6 @@ import net.minecraft.entity.projectile.ProjectileHelper; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.BowItem; import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -40,17 +36,12 @@ public class SkeletonCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xC1C1C1 ); - //TODO theme - forest - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, -4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xC1C1C1 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, -4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -68,13 +59,15 @@ public class SkeletonCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SkeletonCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public SkeletonCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public SkeletonCreeperEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -140,12 +133,4 @@ public class SkeletonCreeperEntity extends _SpecialCreeperEntity { } super.aiStep(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "skeleton" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/SplittingCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/SplittingCreeperEntity.java index a19f3ca..3c79ce6 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/SplittingCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/SplittingCreeperEntity.java @@ -3,20 +3,18 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.SplittingCreeperSpeciesConfig; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.ILivingEntityData; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -35,18 +33,23 @@ public class SplittingCreeperEntity extends _SpecialCreeperEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.7F, 1.99F ); - return new BestiaryInfo( 0x5F9D22, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x5F9D22 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithEyes() + .size( 1.2F, 0.7F, 1.99F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialCreeperEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SplittingCreeperSpeciesConfig( species, false, false, true, + 1, 3 ); } + /** @return This entity's species config. */ + public SplittingCreeperSpeciesConfig getConfig() { return (SplittingCreeperSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Splitting Creeper", @@ -62,21 +65,22 @@ public class SplittingCreeperEntity extends _SpecialCreeperEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SplittingCreeperEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public SplittingCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - getSpecialData().setImmuneToBurning( true ); - setExplodesWhenShot( true ); - xpReward += 2; - extraBabies = random.nextInt( 4 ); - } - /** The number of extra mini creepers spawned on explosion (in addition to the amount based on explosion power). */ private int extraBabies; + public SplittingCreeperEntity( EntityType entityType, World world ) { + super( entityType, world ); + extraBabies = getConfig().SPLITTING.extraBabies.next( random ); + } + /** Override to change this creeper's explosion. */ @Override protected void makeVariantExplosion( float explosionPower ) { @@ -104,9 +108,8 @@ public class SplittingCreeperEntity extends _SpecialCreeperEntity { baby.yBodyRot = yRot; groupData = baby.finalizeSpawn( (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ), SpawnReason.MOB_SUMMONED, groupData, null ); + baby.copyChargedState( this ); baby.setTarget( getTarget() ); - if( isPowered() ) baby.getEntityData().set( DATA_IS_POWERED, true ); - if ( isSupercharged() ) baby.getEntityData().set( IS_SUPERCHARGED, true ); baby.setDeltaMovement( (random.nextDouble() - 0.5) * speed, @@ -130,13 +133,4 @@ public class SplittingCreeperEntity extends _SpecialCreeperEntity { if( saveTag.contains( References.TAG_EXTRA_BABIES, References.NBT_TYPE_NUMERICAL ) ) extraBabies = saveTag.getByte( References.TAG_EXTRA_BABIES ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "splitting" ), - GET_TEXTURE_PATH( "splitting_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java index 60ff144..56edfac 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java @@ -3,9 +3,11 @@ package fathertoast.specialmobs.common.entity.creeper; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.CreeperSpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; +import fathertoast.specialmobs.common.entity.ai.IExplodingMob; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; @@ -24,7 +26,6 @@ import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.pathfinding.PathNodeType; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.IServerWorld; @@ -39,7 +40,7 @@ import java.util.List; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @SpecialMob -public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob<_SpecialCreeperEntity> { +public class _SpecialCreeperEntity extends CreeperEntity implements IExplodingMob, ISpecialMob<_SpecialCreeperEntity> { //--------------- Static Special Mob Hooks ---------------- @@ -47,15 +48,23 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< public static MobFamily.Species<_SpecialCreeperEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ) + .vanillaTextureBaseOnly( "textures/entity/creeper/creeper.png" ) + .experience( 5 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return CreeperEntity.createAttributes(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new CreeperSpeciesConfig( species, false, false, false ); } + /** @return This entity's species config. */ + public CreeperSpeciesConfig getConfig() { return (CreeperSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return CreeperEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Creeper", @@ -73,11 +82,6 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< //--------------- Variant-Specific Breakouts ---------------- - public _SpecialCreeperEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -96,6 +100,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< } /** Override to apply effects when this entity hits a target with a melee attack. */ + @SuppressWarnings( "unused" ) // Not normally used for creepers protected void onVariantAttack( Entity target ) { } /** Called to perform this creeper's explosion 'attack'. */ @@ -159,13 +164,21 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialCreeperEntity.class, DataSerializers.FLOAT ); + public _SpecialCreeperEntity( EntityType entityType, World world ) { + super( entityType, world ); + setCannotExplodeWhileWet( !getConfig().CREEPERS.canExplodeWhileWet.get() ); + setExplodesWhileBurning( getConfig().CREEPERS.explodesWhileBurning.get() ); + setExplodesWhenShot( getConfig().CREEPERS.explodesWhenShot.get() ); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); entityData.define( EXPLODE_FLAGS, (byte) 0 ); - entityData.define( IS_SUPERCHARGED, false ); } /** Called each tick to update this entity. */ @@ -188,9 +201,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< /** Called when this entity is struck by lightning. */ @Override public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) { - if( !isPowered() && random.nextDouble() < 0.1 ) // TODO config - setSupercharged( true ); - + charge(); super.thunderHit( world, lightningBolt ); // Make it less likely for charged "explode while burning" creepers to immediately explode @@ -202,8 +213,13 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - if( world.getLevelData().isThundering() && random.nextDouble() < 0.01 ) { //TODO config - getEntityData().set( DATA_IS_POWERED, true ); + + if( world.getLevelData().isThundering() ) { + final double chargedChance = getConfig().CREEPERS.stormChargeChance.get() < 0.0 ? + MobFamily.CREEPER.config.CREEPERS.familyStormChargeChance.get() : + getConfig().CREEPERS.stormChargeChance.get(); + + if( random.nextDouble() < chargedChance ) charge(); } return groupData; } @@ -213,31 +229,48 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< /** The parameter for creeper explosion properties. This is a combination of boolean flags. */ private static final DataParameter EXPLODE_FLAGS = EntityDataManager.defineId( _SpecialCreeperEntity.class, DataSerializers.BYTE ); - protected static final DataParameter IS_SUPERCHARGED = EntityDataManager.defineId( _SpecialCreeperEntity.class, DataSerializers.BOOLEAN ); + /** The bit for "is supercharged". */ + private static final byte EXPLODE_FLAG_SUPERCHARGED = 0b0001; /** The bit for "cannot explode while wet". */ - private static final byte EXPLODE_FLAG_DEFUSE_IN_WATER = 0b0001; + private static final byte EXPLODE_FLAG_DEFUSE_IN_WATER = 0b0010; /** The bit for "explodes while burning". */ - private static final byte EXPLODE_FLAG_ON_FIRE = 0b0010; + private static final byte EXPLODE_FLAG_ON_FIRE = 0b0100; /** The bit for "explodes when shot". */ - private static final byte EXPLODE_FLAG_WHEN_SHOT = 0b0100; + private static final byte EXPLODE_FLAG_WHEN_SHOT = 0b1000; - - /** @return True if this creeper is super charged. */ - public boolean isSupercharged() { - return entityData.get( IS_SUPERCHARGED ); + /** Called to charge this creeper, potentially supercharging it. */ + public void charge() { + if( !isPowered() ) { + setPowered( true ); + if( MobFamily.CREEPER.config.CREEPERS.superchargeChance.rollChance( random ) ) + setSupercharged( true ); + } } + /** Copy another creeper's charged state. */ + public void copyChargedState( _SpecialCreeperEntity other ) { + setPowered( other.isPowered() ); + setSupercharged( other.isSupercharged() ); + } + + /** Sets this creeper's charged state to the given value. */ + private void setPowered( boolean charged ) { entityData.set( DATA_IS_POWERED, charged ); } + + /** @return True if this creeper is super charged. */ + public boolean isSupercharged() { return getExplodeFlag( EXPLODE_FLAG_SUPERCHARGED ); } + /** Sets this creeper's supercharged state to the given value. */ - public void setSupercharged( boolean superCharged ) { - entityData.set( IS_SUPERCHARGED, superCharged ); + private void setSupercharged( boolean value ) { + if( value && !isPowered() ) setPowered( true ); + setExplodeFlag( EXPLODE_FLAG_SUPERCHARGED, value ); } /** @return True if this creeper is unable to explode while wet. */ public boolean cannotExplodeWhileWet() { return getExplodeFlag( EXPLODE_FLAG_DEFUSE_IN_WATER ); } /** Sets this creeper's capability to explode while wet. */ - public void setCannotExplodeWhileWet( boolean value ) { + private void setCannotExplodeWhileWet( boolean value ) { setExplodeFlag( EXPLODE_FLAG_DEFUSE_IN_WATER, value ); setPathfindingMalus( PathNodeType.WATER, value ? PathNodeType.LAVA.getMalus() : PathNodeType.WATER.getMalus() ); } @@ -246,7 +279,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< public boolean explodesWhileBurning() { return getExplodeFlag( EXPLODE_FLAG_ON_FIRE ); } /** Sets this creeper's property to explode while burning. */ - public void setExplodesWhileBurning( boolean value ) { + private void setExplodesWhileBurning( boolean value ) { setExplodeFlag( EXPLODE_FLAG_ON_FIRE, value ); if( value ) { setPathfindingMalus( PathNodeType.DANGER_FIRE, PathNodeType.DAMAGE_FIRE.getMalus() ); @@ -262,7 +295,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< public boolean explodesWhenShot() { return getExplodeFlag( EXPLODE_FLAG_WHEN_SHOT ); } /** Sets this creeper's property to explode when shot. */ - public void setExplodesWhenShot( boolean value ) { setExplodeFlag( EXPLODE_FLAG_WHEN_SHOT, value ); } + private void setExplodesWhenShot( boolean value ) { setExplodeFlag( EXPLODE_FLAG_WHEN_SHOT, value ); } /** @return The value for a specific explode flag. */ private boolean getExplodeFlag( byte flag ) { return (entityData.get( EXPLODE_FLAGS ) & flag) != 0; } @@ -284,6 +317,11 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< @Override public SpecialMobData<_SpecialCreeperEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -292,16 +330,6 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "creeper/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/creeper/creeper.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- @@ -388,7 +416,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< saveTag.putBoolean( References.TAG_SUPERCHARGED, isSupercharged() ); saveTag.putBoolean( References.TAG_DRY_EXPLODE, cannotExplodeWhileWet() ); - saveTag.putBoolean( References.TAG_WHEN_BURNING_EXPLODE, explodesWhileBurning() ); + saveTag.putBoolean( References.TAG_WHILE_BURNING_EXPLODE, explodesWhileBurning() ); saveTag.putBoolean( References.TAG_WHEN_SHOT_EXPLODE, explodesWhenShot() ); getSpecialData().writeToNBT( saveTag ); @@ -407,8 +435,8 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< if( saveTag.contains( References.TAG_DRY_EXPLODE, References.NBT_TYPE_NUMERICAL ) ) setCannotExplodeWhileWet( saveTag.getBoolean( References.TAG_DRY_EXPLODE ) ); - if( saveTag.contains( References.TAG_WHEN_BURNING_EXPLODE, References.NBT_TYPE_NUMERICAL ) ) - setExplodesWhileBurning( saveTag.getBoolean( References.TAG_WHEN_BURNING_EXPLODE ) ); + if( saveTag.contains( References.TAG_WHILE_BURNING_EXPLODE, References.NBT_TYPE_NUMERICAL ) ) + setExplodesWhileBurning( saveTag.getBoolean( References.TAG_WHILE_BURNING_EXPLODE ) ); if( saveTag.contains( References.TAG_WHEN_SHOT_EXPLODE, References.NBT_TYPE_NUMERICAL ) ) setExplodesWhenShot( saveTag.getBoolean( References.TAG_WHEN_SHOT_EXPLODE ) ); diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/BlindingEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/BlindingEndermanEntity.java index 582afa5..7762104 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/BlindingEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/BlindingEndermanEntity.java @@ -11,7 +11,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -27,9 +26,10 @@ public class BlindingEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFFFFFF ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFFFFF ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 1 ).effectImmune( Effects.BLINDNESS ); } @SpecialMob.LanguageProvider @@ -47,14 +47,15 @@ public class BlindingEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BlindingEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BlindingEndermanEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.BLINDNESS ); - xpReward += 1; - } + public BlindingEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called each tick to update this entity's movement. */ @Override @@ -68,13 +69,4 @@ public class BlindingEndermanEntity extends _SpecialEndermanEntity { target.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen) } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "blinding" ), - GET_TEXTURE_PATH( "blinding_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/IcyEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/IcyEndermanEntity.java index 8afef66..f7fe6f0 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/IcyEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/IcyEndermanEntity.java @@ -25,7 +25,6 @@ import net.minecraft.potion.Effects; import net.minecraft.tags.FluidTags; import net.minecraft.util.DamageSource; import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -45,9 +44,11 @@ public class IcyEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x72959C ); - //TODO theme - ice + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x72959C ).theme( BestiaryInfo.Theme.ICE ) + .uniqueTextureWithEyes() + .addExperience( 1 ).effectImmune( Effects.MOVEMENT_SLOWDOWN ); + } @SpecialMob.LanguageProvider @@ -66,14 +67,16 @@ public class IcyEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return IcyEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public IcyEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.MOVEMENT_SLOWDOWN ); - xpReward += 1; - setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() ); } @@ -189,13 +192,4 @@ public class IcyEndermanEntity extends _SpecialEndermanEntity { FrostWalkerEnchantment.onEntityMoved( this, level, pos, 1 ); onGround = actualOnGround; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "icy" ), - GET_TEXTURE_PATH( "icy_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/LightningEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/LightningEndermanEntity.java index 00a3497..78a05db 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/LightningEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/LightningEndermanEntity.java @@ -12,7 +12,6 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.LightningBoltEntity; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; @@ -29,9 +28,10 @@ public class LightningEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0x4BB4B5 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x4BB4B5 ) + .uniqueTextureWithEyes() + .addExperience( 2 ).fireImmune(); } @SpecialMob.LanguageProvider @@ -49,13 +49,15 @@ public class LightningEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return LightningEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public LightningEndermanEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public LightningEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -71,13 +73,4 @@ public class LightningEndermanEntity extends _SpecialEndermanEntity { /** Called when this entity is struck by lightning. */ @Override public void thunderHit( ServerWorld world, LightningBoltEntity lightningBolt ) { } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "lightning" ), - GET_TEXTURE_PATH( "lightning_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/MiniEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/MiniEndermanEntity.java index 6f385d4..a291569 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/MiniEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/MiniEndermanEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.enderman; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.world.World; @@ -26,17 +23,12 @@ public class MiniEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.5F, 0.99F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialEndermanEntity.createAttributes() ) - .addAttribute( Attributes.ATTACK_DAMAGE, -2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.LOW ) + .size( 0.35F, 0.5F, 0.99F ) + .addExperience( 1 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, -2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -53,15 +45,16 @@ public class MiniEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MiniEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public MiniEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 0.35F ); maxUpStep = 0.5F; - xpReward += 1; } - - // None } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/MirageEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/MirageEndermanEntity.java index fc2c6c7..cbb2061 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/MirageEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/MirageEndermanEntity.java @@ -3,19 +3,15 @@ package fathertoast.specialmobs.common.entity.enderman; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -31,16 +27,11 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xC2BC84, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - desert - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialEndermanEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xC2BC84 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.DESERT ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ); } @SpecialMob.LanguageProvider @@ -60,21 +51,23 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MirageEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public MirageEndermanEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - /** Whether this mirage enderman is fake. */ public boolean isFake = false; + public MirageEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); } + /** Sets this mirage enderman as fake. */ public void setFake() { isFake = true; - xpReward = 0; + setExperience( 0 ); //noinspection ConstantConditions getAttribute( Attributes.ATTACK_DAMAGE ).setBaseValue( 0.0 ); } @@ -112,18 +105,14 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity { protected boolean teleport( double x, double y, double z ) { if( isFake ) return false; - double xI = getX(); - double yI = getY(); - double zI = getZ(); - if( super.teleport( x, y, z ) ) { - mirage( xI, yI, zI ); + mirage(); return true; } return false; } - private void mirage( double xI, double yI, double zI ) { + private void mirage() { if( !isFake && getTarget() != null ) { final MirageEndermanEntity mirage = SPECIES.entityType.get().create( level ); if( mirage == null ) return; @@ -134,10 +123,10 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity { // Return one of the endermen to the initial position (either the real or the fake) if( random.nextInt( 4 ) == 0 ) { - moveTo( xI, yI, zI ); + moveTo( xo, yo, zo ); } else { - mirage.moveTo( xI, yI, zI ); + mirage.moveTo( xo, yo, zo ); } mirage.setHealth( getHealth() ); @@ -163,13 +152,4 @@ public class MirageEndermanEntity extends _SpecialEndermanEntity { if( saveTag.contains( References.TAG_IS_FAKE, References.NBT_TYPE_NUMERICAL ) ) isFake = saveTag.getBoolean( References.TAG_IS_FAKE ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "mirage" ), - GET_TEXTURE_PATH( "mirage_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/ThiefEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/ThiefEndermanEntity.java index bf3729b..55ef519 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/ThiefEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/ThiefEndermanEntity.java @@ -3,17 +3,14 @@ package fathertoast.specialmobs.common.entity.enderman; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; @@ -33,15 +30,11 @@ public class ThiefEndermanEntity extends _SpecialEndermanEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x04FA00, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialEndermanEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x04FA00 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -59,16 +52,18 @@ public class ThiefEndermanEntity extends _SpecialEndermanEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return ThiefEndermanEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public ThiefEndermanEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - private int teleportTargetDelay; + public ThiefEndermanEntity( EntityType entityType, World world ) { super( entityType, world ); } + /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -118,13 +113,4 @@ public class ThiefEndermanEntity extends _SpecialEndermanEntity { super.aiStep(); if( !level.isClientSide() ) teleportTargetDelay--; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "thief" ), - GET_TEXTURE_PATH( "thief_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/enderman/_SpecialEndermanEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/enderman/_SpecialEndermanEntity.java index a75f6c3..5722061 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/enderman/_SpecialEndermanEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/enderman/_SpecialEndermanEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.enderman; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.util.References; @@ -19,13 +18,9 @@ import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.IServerWorld; import net.minecraft.world.World; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @@ -39,14 +34,14 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo public static MobFamily.Species<_SpecialEndermanEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ) + .vanillaTextureWithEyes( "textures/entity/enderman/enderman.png", "textures/entity/enderman/enderman_eyes.png" ) + .experience( 5 ).waterSensitive(); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return EndermanEntity.createAttributes(); - } + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return EndermanEntity.createAttributes(); } @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { @@ -65,12 +60,6 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo //--------------- Variant-Specific Breakouts ---------------- - public _SpecialEndermanEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - getSpecialData().setDamagedByWater( true ); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -103,20 +92,16 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialEndermanEntity.class, DataSerializers.FLOAT ); + public _SpecialEndermanEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); - } - - /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ - @Nullable - public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, - @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { - groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - // TODO anything? - return groupData; + specialData = new SpecialMobData<>( this, SCALE ); } @@ -128,6 +113,11 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo @Override public SpecialMobData<_SpecialEndermanEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -136,19 +126,6 @@ public class _SpecialEndermanEntity extends EndermanEntity implements ISpecialMo @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "enderman/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/enderman/enderman.png" ), - new ResourceLocation( "textures/entity/enderman/enderman_eyes.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/BabyGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/BabyGhastEntity.java index 5b87bed..33027b9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/BabyGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/BabyGhastEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.ghast; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.util.SoundEvent; @@ -28,16 +25,11 @@ public class BabyGhastEntity extends _SpecialGhastEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 1.0F, 1.0F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.DISABLED ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.DISABLED ) + .size( 0.25F, 1.0F, 1.0F ) + .experience( 1 ).disableRangedAttack() + .addToAttribute( Attributes.ATTACK_DAMAGE, -1.0 ); } @SpecialMob.LanguageProvider @@ -54,21 +46,15 @@ public class BabyGhastEntity extends _SpecialGhastEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BabyGhastEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BabyGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.25F ); - xpReward = 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage -= 1.0F; - disableRangedAI(); - } + public BabyGhastEntity( EntityType entityType, World world ) { super( entityType, world ); } /** @return The sound this entity makes idly. */ @Override diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java index 82fd165..4461587 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java @@ -4,126 +4,117 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.core.register.SMItems; -import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.entity.projectile.CorporealShiftFireballEntity; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.common.util.Constants; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault @SpecialMob public class CorporealShiftGhastEntity extends _SpecialGhastEntity { - + //--------------- Static Special Mob Hooks ---------------- - + @SpecialMob.SpeciesReference public static MobFamily.Species SPECIES; - + @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo(EntityType.Builder entityType ) { - entityType.sized( 6.0F, 6.0F ); - return new BestiaryInfo( 0xA7FF9B, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA7FF9B ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithAnimation() + .addExperience( 4 ).regen( 80 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ARMOR, 0.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 0.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); - } - + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Corporeal Shift Ghast", "", "", "", "", "", "" );//TODO } - + @SpecialMob.LootTableProvider public static void buildLootTable( LootTableBuilder loot ) { addBaseLoot( loot ); - // TODO - Uh uhm uhhhhh hmmm.. loot.addSemicommonDrop( "semicommon", SMItems.INCORPOREAL_FIREBALL.get() ); } - + @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return CorporealShiftGhastEntity::new; } - - + + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + + //--------------- Variant-Specific Implementations ---------------- - - public static final DataParameter CORPOREAL = EntityDataManager.defineId(CorporealShiftGhastEntity.class, DataSerializers.BOOLEAN); - + + public static final DataParameter CORPOREAL = EntityDataManager.defineId( CorporealShiftGhastEntity.class, DataSerializers.BOOLEAN ); + private final int maxShiftTime = 600; private int shiftTime = maxShiftTime; - - public CorporealShiftGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setRegenerationTime( 80 ); - getSpecialData().setBaseScale( 1.0F ); - xpReward += 2; - } - + + public CorporealShiftGhastEntity( EntityType entityType, World world ) { super( entityType, world ); } + @Override protected void defineSynchedData() { super.defineSynchedData(); - entityData.define(CORPOREAL, false); + entityData.define( CORPOREAL, false ); } - + @Override public void tick() { super.tick(); - - if ( --shiftTime <= 0 ) { - if ( !level.isClientSide ) { + + if( --shiftTime <= 0 ) { + if( !level.isClientSide ) { shiftTime = maxShiftTime; - entityData.set(CORPOREAL, !entityData.get(CORPOREAL)); - spawnShiftSmoke((ServerWorld)level); + setCorporeal( !isCorporeal() ); + spawnShiftSmoke( (ServerWorld) level ); } } } - - private void spawnShiftSmoke(ServerWorld world) { - world.sendParticles(ParticleTypes.CLOUD, this.getX(), this.getY(), this.getZ(), 25, 0.0, 0.0, 0.0, 0.4); + + private void spawnShiftSmoke( ServerWorld world ) { + world.sendParticles( ParticleTypes.CLOUD, this.getX(), this.getY(), this.getZ(), 25, 0.0, 0.0, 0.0, 0.4 ); } - - public boolean isCorporeal() { - return entityData.get(CORPOREAL); - } - + + public boolean isCorporeal() { return entityData.get( CORPOREAL ); } + + private void setCorporeal( boolean value ) { entityData.set( CORPOREAL, value ); } + /** Override to change this ghast's explosion power multiplier. */ @Override protected int getVariantExplosionPower( int radius ) { return Math.round( radius * 2.5F ); } - + /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 ); - - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; + + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() ); double dX = target.getX() - (getX() + lookVec.x) + getRandom().nextGaussian() * accelVariance; double dY = target.getY( 0.5 ) - (0.5 + getY( 0.5 )); double dZ = target.getZ() - (getZ() + lookVec.z) + getRandom().nextGaussian() * accelVariance; - + final CorporealShiftFireballEntity fireball = new CorporealShiftFireballEntity( level, this, dX, dY, dZ ); fireball.explosionPower = getVariantExplosionPower( getExplosionPower() ); fireball.setPos( @@ -132,40 +123,29 @@ public class CorporealShiftGhastEntity extends _SpecialGhastEntity { getZ() + lookVec.z ); level.addFreshEntity( fireball ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "corporeal_shift" ), - null, - GET_TEXTURE_PATH( "corporeal_shift_shoot" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - - + + //--------------- SpecialMobData Hooks ---------------- - + /** @return Attempts to damage this entity; returns true if the hit was successful. */ @Override - public boolean hurt(DamageSource source, float amount ) { - return isCorporeal() && super.hurt(source, amount); + public boolean hurt( DamageSource source, float amount ) { + return isCorporeal() && super.hurt( source, amount ); } - - /** Saves data to this entity's base NBT compound that is specific to its subclass. */ + + /** Override to save data to this entity's NBT data. */ @Override - public void addAdditionalSaveData( CompoundNBT tag ) { - super.addAdditionalSaveData( tag ); - tag.putInt("ShiftTime", shiftTime); + public void addVariantSaveData( CompoundNBT saveTag ) { + saveTag.putBoolean( References.TAG_IS_SHIFTED, isCorporeal() ); + saveTag.putShort( References.TAG_SHIFT_TIME, (short) shiftTime ); } - - /** Loads data from this entity's base NBT compound that is specific to its subclass. */ + + /** Override to load data from this entity's NBT data. */ @Override - public void readAdditionalSaveData( CompoundNBT tag ) { - super.readAdditionalSaveData( tag ); - - if (tag.contains("ShiftTime", Constants.NBT.TAG_ANY_NUMERIC)) { - shiftTime = tag.getInt("ShiftTime"); - } + public void readVariantSaveData( CompoundNBT saveTag ) { + if( saveTag.contains( References.TAG_IS_SHIFTED, References.NBT_TYPE_NUMERICAL ) ) + setCorporeal( saveTag.getBoolean( References.TAG_IS_SHIFTED ) ); + if( saveTag.contains( References.TAG_SHIFT_TIME, References.NBT_TYPE_NUMERICAL ) ) + shiftTime = saveTag.getShort( References.TAG_SHIFT_TIME ); } -} +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/FighterGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/FighterGhastEntity.java index bc04729..130534c 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/FighterGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/FighterGhastEntity.java @@ -4,17 +4,14 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,19 +27,14 @@ public class FighterGhastEntity extends _SpecialGhastEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 2.0F, 2.0F ); - return new BestiaryInfo( 0x7A1300 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x7A1300 ) + .uniqueTextureWithAnimation() + .size( 0.5F, .0F, 2.0F ) + .addExperience( 1 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } @SpecialMob.LanguageProvider @@ -60,21 +52,15 @@ public class FighterGhastEntity extends _SpecialGhastEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FighterGhastEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FighterGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.5F ); - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; - disableRangedAI(); - } + public FighterGhastEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ protected void onVariantAttack( Entity target ) { @@ -82,14 +68,4 @@ public class FighterGhastEntity extends _SpecialGhastEntity { MobHelper.causeLifeLoss( (LivingEntity) target, 2.0F ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fighter" ), - null, - GET_TEXTURE_PATH( "fighter_shooting" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/KingGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/KingGhastEntity.java index 88c2911..545c7e2 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/KingGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/KingGhastEntity.java @@ -3,16 +3,12 @@ package fathertoast.specialmobs.common.entity.ghast; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,19 +24,14 @@ public class KingGhastEntity extends _SpecialGhastEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 6.0F, 6.0F ); - return new BestiaryInfo( 0xE8C51A, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.6 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE8C51A ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithAnimation() + .size( 1.5F, 6.0F, 6.0F ) + .addExperience( 4 ).regen( 30 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.6 ); } @SpecialMob.LanguageProvider @@ -59,33 +50,17 @@ public class KingGhastEntity extends _SpecialGhastEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return KingGhastEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public KingGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - getSpecialData().setRegenerationTime( 30 ); - xpReward += 4; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 4.0F; - } + public KingGhastEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this ghast's explosion power multiplier. */ @Override protected int getVariantExplosionPower( int radius ) { return Math.round( radius * 2.5F ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "king" ), - null, - GET_TEXTURE_PATH( "king_shooting" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/QueenGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/QueenGhastEntity.java index d6dbfdb..989bad5 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/QueenGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/QueenGhastEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.ghast; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.QueenGhastSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -11,11 +12,9 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.ILivingEntityData; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -33,20 +32,24 @@ public class QueenGhastEntity extends _SpecialGhastEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 5.0F, 5.0F ); - return new BestiaryInfo( 0xCE0Aff ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xCE0Aff ) + .uniqueTextureWithAnimation() + .size( 1.25F, 5.0F, 5.0F ) + .addExperience( 2 ).regen( 20 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.6 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.6 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new QueenGhastSpeciesConfig( species, 3, 6, 4, 10 ); } + /** @return This entity's species config. */ + public QueenGhastSpeciesConfig getConfig() { return (QueenGhastSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Queen Ghast", @@ -63,6 +66,11 @@ public class QueenGhastEntity extends _SpecialGhastEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return QueenGhastEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -73,18 +81,8 @@ public class QueenGhastEntity extends _SpecialGhastEntity { public QueenGhastEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.25F ); - getSpecialData().setRegenerationTime( 20 ); - xpReward += 2; - - babies = 3 + random.nextInt( 4 ); - summons = 4 + random.nextInt( 7 ); - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; + babies = getConfig().QUEEN.babies.next( random ); + summons = getConfig().QUEEN.summons.next( random ); } /** Called to attack the target with a ranged attack. */ @@ -160,14 +158,4 @@ public class QueenGhastEntity extends _SpecialGhastEntity { if( saveTag.contains( References.TAG_SUMMONS, References.NBT_TYPE_NUMERICAL ) ) summons = saveTag.getByte( References.TAG_SUMMONS ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "queen" ), - null, - GET_TEXTURE_PATH( "queen_shooting" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/UnholyGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/UnholyGhastEntity.java index b8caa89..53dd5b9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/UnholyGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/UnholyGhastEntity.java @@ -4,7 +4,6 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -12,13 +11,11 @@ import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -34,18 +31,14 @@ public class UnholyGhastEntity extends _SpecialGhastEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 2.0F, 2.0F ); - return new BestiaryInfo( 0x7AC754, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialGhastEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.7 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x7AC754 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithAnimation() + .size( 0.5F, 2.0F, 2.0F ) + .addExperience( 4 ).undead().disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.7 ); } @SpecialMob.LanguageProvider @@ -64,21 +57,15 @@ public class UnholyGhastEntity extends _SpecialGhastEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return UnholyGhastEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public UnholyGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.5F ); - xpReward += 4; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; - disableRangedAI(); - } + public UnholyGhastEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ protected void onVariantAttack( Entity target ) { @@ -120,14 +107,4 @@ public class UnholyGhastEntity extends _SpecialGhastEntity { } super.aiStep(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "unholy" ), - null, - GET_TEXTURE_PATH( "unholy_shooting" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/_SpecialGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/_SpecialGhastEntity.java index 69cbb3b..3ce6be7 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/ghast/_SpecialGhastEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/_SpecialGhastEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.ghast; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.entity.ai.AIHelper; @@ -32,7 +31,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; @@ -53,11 +51,14 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob public static MobFamily.Species<_SpecialGhastEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xBCBCBC ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xBCBCBC ) + .vanillaTextureWithAnimation( "textures/entity/ghast/ghast.png", "textures/entity/ghast/ghast_shooting.png" ) + .experience( 5 ).fireImmune() + .fireballAttack( 0.0, 20, 40, 64.0 ); } - @SpecialMob.AttributeCreator + @SpecialMob.AttributeSupplier public static AttributeModifierMap.MutableAttribute createAttributes() { return GhastEntity.createAttributes().add( Attributes.ATTACK_DAMAGE, 4.0 ); } @@ -79,13 +80,6 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob //--------------- Variant-Specific Breakouts ---------------- - public _SpecialGhastEntity( EntityType entityType, World world ) { - super( entityType, world ); - moveControl = new SimpleFlyingMovementController( this ); - reassessAttackGoal(); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -94,24 +88,18 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob AIHelper.removeGoals( goalSelector, 7 ); // GhastEntity.LookAroundGoal & GhastEntity.FireballAttackGoal goalSelector.addGoal( 7, new SpecialGhastLookAroundGoal( this ) ); - // Allow ghasts to target things not directly horizontal to them (why was this ever added?) TODO config - AIHelper.removeGoals( targetSelector, NearestAttackableTargetGoal.class ); - targetSelector.addGoal( 1, new NearestAttackableTargetGoal<>( this, PlayerEntity.class, true ) ); + // Allow ghasts to target things not directly horizontal to them (why was this ever added?) + if( MobFamily.GHAST.config.GHASTS.allowVerticalTargeting.get() ) { + AIHelper.removeGoals( targetSelector, NearestAttackableTargetGoal.class ); + targetSelector.addGoal( 1, new NearestAttackableTargetGoal<>( this, PlayerEntity.class, true ) ); + } - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedAttackSpread = 0.0F; - getSpecialData().rangedAttackCooldown = 20; - getSpecialData().rangedAttackMaxCooldown = 60; - getSpecialData().rangedAttackMaxRange = 64.0F; registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { getSpecialData().rangedAttackMaxRange = 0.0F; } - /** Override to change this entity's attack goal priority. */ protected int getVariantAttackPriority() { return 4; } @@ -120,7 +108,7 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob public void performRangedAttack( LivingEntity target, float damageMulti ) { if( !isSilent() ) level.levelEvent( null, References.EVENT_GHAST_SHOOT, blockPosition(), 0 ); - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); final Vector3d lookVec = getViewVector( 1.0F ).scale( getBbWidth() ); double dX = target.getX() - (getX() + lookVec.x) + getRandom().nextGaussian() * accelVariance; double dY = target.getY( 0.5 ) - (0.5 + getY( 0.5 )); @@ -163,11 +151,18 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob /** This entity's attack AI. */ private Goal currentAttackAI; + public _SpecialGhastEntity( EntityType entityType, World world ) { + super( entityType, world ); + moveControl = new SimpleFlyingMovementController( this ); + reassessAttackGoal(); + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ @@ -191,7 +186,7 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob if( level != null && !level.isClientSide ) { if( currentAttackAI != null ) goalSelector.removeGoal( currentAttackAI ); - currentAttackAI = getSpecialData().rangedAttackMaxRange > 0.0F ? + currentAttackAI = getSpecialData().getRangedAttackMaxRange() > 0.0F ? new SpecialGhastFireballAttackGoal( this ) : new SpecialGhastMeleeAttackGoal( this ); @@ -208,6 +203,11 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob @Override public SpecialMobData<_SpecialGhastEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -216,20 +216,6 @@ public class _SpecialGhastEntity extends GhastEntity implements IRangedAttackMob @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "ghast/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/ghast/ghast.png" ), - null, - new ResourceLocation( "textures/entity/ghast/ghast_shooting.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/BouncingMagmaCubeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/BouncingMagmaCubeEntity.java index ab9a059..bc7218c 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/BouncingMagmaCubeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/BouncingMagmaCubeEntity.java @@ -11,7 +11,6 @@ import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.fluid.Fluid; import net.minecraft.item.Items; @@ -19,7 +18,6 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.pathfinding.PathNavigator; import net.minecraft.pathfinding.PathNodeType; import net.minecraft.tags.FluidTags; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -35,10 +33,12 @@ public class BouncingMagmaCubeEntity extends _SpecialMagmaCubeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xB333B3 ); - //TODO theme - mountain + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xB333B3 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fallImmune() + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -56,24 +56,19 @@ public class BouncingMagmaCubeEntity extends _SpecialMagmaCubeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BouncingMagmaCubeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public BouncingMagmaCubeEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - slimeExperienceValue += 1; - setPathfindingMalus( PathNodeType.LAVA, PathNodeType.WALKABLE.getMalus() ); } - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size ); - multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); - } - /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { AIHelper.removeGoals( goalSelector, 1 ); // SlimeEntity.FloatGoal @@ -104,12 +99,4 @@ public class BouncingMagmaCubeEntity extends _SpecialMagmaCubeEntity { public void readVariantSaveData( CompoundNBT saveTag ) { setPathfindingMalus( PathNodeType.LAVA, PathNodeType.WALKABLE.getMalus() ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "bouncing" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/HardenedMagmaCubeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/HardenedMagmaCubeEntity.java index 072a323..659bfa5 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/HardenedMagmaCubeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/HardenedMagmaCubeEntity.java @@ -12,7 +12,6 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -29,9 +28,13 @@ public class HardenedMagmaCubeEntity extends _SpecialMagmaCubeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 3.06F, 3.06F ); - return new BestiaryInfo( 0xDF7679, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDF7679 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureBaseOnly() + .size( 1.5F, 3.06F, 3.06F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 8.0 ).addToAttribute( Attributes.ARMOR, 16.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 1.0 ); } @SpecialMob.LanguageProvider @@ -49,21 +52,15 @@ public class HardenedMagmaCubeEntity extends _SpecialMagmaCubeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HardenedMagmaCubeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public HardenedMagmaCubeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - slimeExperienceValue += 2; - } - - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size + 8.0 ); - addAttribute( Attributes.ARMOR, 8.0 ); - } + public HardenedMagmaCubeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -86,12 +83,4 @@ public class HardenedMagmaCubeEntity extends _SpecialMagmaCubeEntity { setDeltaMovement( getDeltaMovement().multiply( 0.2, 1.0, 0.2 ) ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "hardened" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/StickyMagmaCubeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/StickyMagmaCubeEntity.java index 94eefbf..6ee6cef 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/StickyMagmaCubeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/StickyMagmaCubeEntity.java @@ -12,7 +12,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,8 +28,11 @@ public class StickyMagmaCubeEntity extends _SpecialMagmaCubeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x9D733F ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x9D733F ) + .uniqueTextureBaseOnly() + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 8.0 ); } @SpecialMob.LanguageProvider @@ -48,23 +50,19 @@ public class StickyMagmaCubeEntity extends _SpecialMagmaCubeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return StickyMagmaCubeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public StickyMagmaCubeEntity( EntityType entityType, World world ) { - super( entityType, world ); - slimeExperienceValue += 2; - } - private final DamageSource grabDamageSource = DamageSource.mobAttack( this ).bypassArmor().bypassMagic(); private int grabTime; - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 4.0 * size ); - } + public StickyMagmaCubeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -90,12 +88,4 @@ public class StickyMagmaCubeEntity extends _SpecialMagmaCubeEntity { } } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "sticky" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/VolatileMagmaCubeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/VolatileMagmaCubeEntity.java index b24dcb5..05c1f79 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/VolatileMagmaCubeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/VolatileMagmaCubeEntity.java @@ -3,15 +3,15 @@ package fathertoast.specialmobs.common.entity.magmacube; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.entity.ai.IExplodingMob; +import fathertoast.specialmobs.common.entity.ai.goal.SpecialSwellGoal; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.AreaEffectCloudEntity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -21,19 +21,17 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.potion.EffectInstance; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @SpecialMob -public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity { +public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity implements IExplodingMob { //--------------- Static Special Mob Hooks ---------------- @@ -41,8 +39,11 @@ public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x331133 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x331133 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 2.0 ); } @SpecialMob.LanguageProvider @@ -60,39 +61,34 @@ public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return VolatileMagmaCubeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public VolatileMagmaCubeEntity( EntityType entityType, World world ) { - super( entityType, world ); - slimeExperienceValue += 2; - } - private static final byte MAX_FUSE = 30; private int fuse = 0; - private int swellDir = 0; private boolean ignited = false; - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size ); - } + public VolatileMagmaCubeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - goalSelector.addGoal( 0, new SlimeSwellGoal( this ) ); + goalSelector.addGoal( 0, new SpecialSwellGoal<>( this ) ); } /** Called each tick to update this entity. */ @Override public void tick() { if( isAlive() && !level.isClientSide() ) { - if( ignited ) swellDir = 1; + if( ignited ) setSwellDir( 1 ); - if( swellDir > 0 ) { + if( getSwellDir() > 0 ) { if( fuse == 0 ) { playSound( SoundEvents.CREEPER_PRIMED, 1.0F, 0.5F ); } @@ -106,9 +102,9 @@ public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity { changeFuse( +1 ); } } - else if( swellDir < 0 && fuse > 0 ) { + else if( getSwellDir() < 0 && fuse > 0 ) { changeFuse( -1 ); - if( fuse <= 0 ) swellDir = 0; + if( fuse <= 0 ) setSwellDir( 0 ); } } super.tick(); @@ -187,51 +183,20 @@ public class VolatileMagmaCubeEntity extends _SpecialMagmaCubeEntity { @Override protected IParticleData getParticleType() { return ParticleTypes.SMOKE; } - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "volatile" ) - }; - /** @return All default textures for this entity. */ + //--------------- IExplodingEntity Implementations ---------------- + + private int swellDir = 0; + + /** Sets this exploding entity's swell direction. */ @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public void setSwellDir( int value ) { swellDir = value; } + /** @return This exploding entity's swell direction. */ + @Override + public int getSwellDir() { return swellDir; } - //--------------- Nested Classes ---------------- - - /** The "creeper swell" goal repurposed for use on a slime. */ - private static class SlimeSwellGoal extends Goal { - - private final VolatileMagmaCubeEntity slime; - - private LivingEntity target; - - public SlimeSwellGoal( VolatileMagmaCubeEntity entity ) { - slime = entity; - setFlags( EnumSet.of( Flag.MOVE ) ); - } - - public boolean canUse() { - final LivingEntity target = slime.getTarget(); - return slime.swellDir > 0 || target != null && slime.distanceToSqr( target ) < 9.0F + (slime.getSize() - 1) * 2.0F; - } - - public void start() { - slime.getNavigation().stop(); - target = slime.getTarget(); - } - - public void stop() { - slime.swellDir = -1; - target = null; - } - - public void tick() { - if( target == null || slime.distanceToSqr( target ) > 49.0 || !slime.getSensing().canSee( target ) ) { - slime.swellDir = -1; - } - else { - slime.swellDir = 1; - } - } - } + /** @return Additional range from its target at which this entity will start to explode. */ + @Override + public double getExtraRange() { return (getSize() - 1) * 2.0F; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/_SpecialMagmaCubeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/_SpecialMagmaCubeEntity.java index 8a0b61d..94446cf 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/magmacube/_SpecialMagmaCubeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/magmacube/_SpecialMagmaCubeEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.magmacube; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.util.References; @@ -11,20 +10,18 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.AttributeModifierManager; import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; import net.minecraft.entity.monster.MagmaCubeEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.SnowballEntity; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -41,11 +38,13 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial public static MobFamily.Species<_SpecialMagmaCubeEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFCFC00 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFCFC00 ) + .vanillaTextureBaseOnly( "textures/entity/slime/magmacube.png" ) + .experience( 0 ); } - @SpecialMob.AttributeCreator + @SpecialMob.AttributeSupplier public static AttributeModifierMap.MutableAttribute createAttributes() { return MagmaCubeEntity.createAttributes(); // Slimes define their attributes elsewhere based on size } @@ -67,14 +66,6 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial //--------------- Variant-Specific Breakouts ---------------- - public _SpecialMagmaCubeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - - /** Override to modify this slime's base attributes by size. */ - protected void modifyVariantAttributes( int size ) { } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -107,62 +98,39 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialMagmaCubeEntity.class, DataSerializers.FLOAT ); - protected int slimeExperienceValue = 0; + /** Used to reset slimes' attributes to their freshly spawned state so attribute adjustments may be reapplied on size change. */ + private static ListNBT magmaCubeAttributeSnapshot; + + private static ListNBT getAttributeSnapshot() { + if( magmaCubeAttributeSnapshot == null ) + magmaCubeAttributeSnapshot = new AttributeModifierManager( createAttributes().build() ).save(); + return magmaCubeAttributeSnapshot; + } + + private int slimeExperienceValue = 0; + + public _SpecialMagmaCubeEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().initialize(); + } /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Sets this slime's size, optionally resetting its health to max. */ @Override protected void setSize( int size, boolean resetHealth ) { + // We must reset all attributes and reapply changes since slimes set attribute base values on size change + getAttributes().load( getAttributeSnapshot() ); super.setSize( size, resetHealth ); + getSpecies().config.GENERAL.attributeChanges.apply( this ); - modifyVariantAttributes( size ); if( resetHealth ) setHealth( getMaxHealth() ); - xpReward = size + slimeExperienceValue; - } - - /** - * Alters this magma cube's base attribute by adding an amount to it. - * Do NOT use this for move speed, instead use {@link #multAttribute(Attribute, double)} - */ - protected void addAttribute( Attribute attribute, double amount ) { - if( attribute != Attributes.MAX_HEALTH && attribute != Attributes.ARMOR && attribute != Attributes.ATTACK_DAMAGE && attribute != Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Magma cube relative attributes are only health, armor, damage, and speed!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() + amount ); - } - - /** - * Alters this magma cube's base attribute by multiplying it by an amount. - * Mainly use this for move speed, for other attributes use {@link #addAttribute(Attribute, double)} - */ - protected void multAttribute( Attribute attribute, double amount ) { - if( attribute != Attributes.MAX_HEALTH && attribute != Attributes.ARMOR && attribute != Attributes.ATTACK_DAMAGE && attribute != Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Magma cube relative attributes are only health, armor, damage, and speed!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() * amount ); - } - - /** Sets this magma cube's base attribute. */ - protected void setAttribute( Attribute attribute, double amount ) { - if( attribute == Attributes.MAX_HEALTH || attribute == Attributes.ARMOR || attribute == Attributes.ATTACK_DAMAGE || attribute == Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Use magma cube relative attribute!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( amount ); + setExperience( getExperience() ); // Update for new size } @@ -174,6 +142,11 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial @Override public SpecialMobData<_SpecialMagmaCubeEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return slimeExperienceValue; } // Slime base xp @@ -185,18 +158,6 @@ public class _SpecialMagmaCubeEntity extends MagmaCubeEntity implements ISpecial xpReward = getSize() + xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "magmacube/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/slime/magmacube.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java index a3faaa0..2fc8171 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java @@ -6,12 +6,12 @@ import fathertoast.specialmobs.common.core.register.SMEntities; import fathertoast.specialmobs.common.core.register.SMItems; import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; import fathertoast.specialmobs.common.util.References; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.AbstractFireballEntity; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; @@ -31,177 +31,180 @@ import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.fml.network.NetworkHooks; import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault public class CorporealShiftFireballEntity extends AbstractFireballEntity { - - private static final DataParameter CORPOREAL = EntityDataManager.defineId(CorporealShiftFireballEntity.class, DataSerializers.BOOLEAN); - + + private static final DataParameter CORPOREAL = EntityDataManager.defineId( CorporealShiftFireballEntity.class, DataSerializers.BOOLEAN ); + public int explosionPower = 1; private boolean shouldExplode = false; - + @Nullable private LivingEntity target; - - - public CorporealShiftFireballEntity(EntityType entityType, World world) { - super(entityType, world); + + + public CorporealShiftFireballEntity( EntityType entityType, World world ) { + super( entityType, world ); } - - public CorporealShiftFireballEntity(World world, CorporealShiftGhastEntity ghast, double x, double y, double z) { - super(SMEntities.CORPOREAL_FIREBALL.get(), ghast, x, y, z, world); - setCorporeal(ghast.isCorporeal()); + + public CorporealShiftFireballEntity( World world, CorporealShiftGhastEntity ghast, double x, double y, double z ) { + super( SMEntities.CORPOREAL_FIREBALL.get(), ghast, x, y, z, world ); + setCorporeal( ghast.isCorporeal() ); target = ghast.getTarget(); - setItem(isCorporeal() ? new ItemStack(Items.FIRE_CHARGE) : new ItemStack(SMItems.INCORPOREAL_FIREBALL.get())); + setItem( isCorporeal() ? new ItemStack( Items.FIRE_CHARGE ) : new ItemStack( SMItems.INCORPOREAL_FIREBALL.get() ) ); } - - public CorporealShiftFireballEntity(World world, PlayerEntity owner, LivingEntity target, double x, double y, double z) { - super(SMEntities.CORPOREAL_FIREBALL.get(), owner, x, y, z, world); - setCorporeal(false); + + public CorporealShiftFireballEntity( World world, PlayerEntity owner, LivingEntity target, double x, double y, double z ) { + super( SMEntities.CORPOREAL_FIREBALL.get(), owner, x, y, z, world ); + setCorporeal( false ); this.target = target; - setItem(new ItemStack(SMItems.INCORPOREAL_FIREBALL.get())); + setItem( new ItemStack( SMItems.INCORPOREAL_FIREBALL.get() ) ); } - + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Corporeal Shift Fireball", "", "", "", "", "", "" );//TODO } - + @Override protected void defineSynchedData() { super.defineSynchedData(); - entityData.define(CORPOREAL, true); + entityData.define( CORPOREAL, true ); } - + public boolean isCorporeal() { - return entityData.get(CORPOREAL); + return entityData.get( CORPOREAL ); } - - public void setCorporeal(boolean corporeal) { - entityData.set(CORPOREAL, corporeal); + + public void setCorporeal( boolean corporeal ) { + entityData.set( CORPOREAL, corporeal ); } - + @Override public void tick() { super.tick(); - - if ( !level.isClientSide && !isCorporeal() ) { + + if( !level.isClientSide && !isCorporeal() ) { // Fizzle out and die when the target is dead or lost, // or else the fireball goes bonkers. - if ( target == null || !target.isAlive() ) { - playSound(SoundEvents.FIRE_EXTINGUISH, 1.0F, 1.0F); + if( target == null || !target.isAlive() ) { + playSound( SoundEvents.FIRE_EXTINGUISH, 1.0F, 1.0F ); remove(); return; } // Follow target Vector3d vector3d = new Vector3d( target.getX() - this.getX(), (target.getY() + (target.getEyeHeight() / 2)) - this.getY(), target.getZ() - this.getZ() ); - setDeltaMovement(vector3d.normalize().scale(0.5)); + setDeltaMovement( vector3d.normalize().scale( 0.5 ) ); } - - if ( !level.isClientSide && shouldExplode ) + + if( !level.isClientSide && shouldExplode ) explode(); } - + private void explode() { boolean mobGrief = ForgeEventFactory.getMobGriefingEvent( level, getOwner() ); Explosion.Mode mode = mobGrief ? Explosion.Mode.DESTROY : Explosion.Mode.NONE; - - level.explode( null, this.getX(), this.getY(), this.getZ(), (float)explosionPower, mobGrief, mode ); + + level.explode( null, this.getX(), this.getY(), this.getZ(), (float) explosionPower, mobGrief, mode ); target = null; remove(); } - + @Override protected boolean shouldBurn() { // Hee hee hee haw return isCorporeal(); } - + @Override protected void onHit( RayTraceResult traceResult ) { super.onHit( traceResult ); - + // Only go boom if the fireball is corporeal. // If not, pass through blocks to be a menace. - if ( !level.isClientSide && isCorporeal() ) { + if( !level.isClientSide && isCorporeal() ) { shouldExplode = true; } } - + @Override protected void onHitEntity( EntityRayTraceResult traceResult ) { - super.onHitEntity(traceResult); - - if ( !this.level.isClientSide ) { + super.onHitEntity( traceResult ); + + if( !this.level.isClientSide ) { Entity target = traceResult.getEntity(); Entity owner = getOwner(); - - if (!isCorporeal()) { + + if( !isCorporeal() ) { // TODO - Figure out why this is cringe // TODO part 2. - What the fuck // TODO part 3. - HELP - SpecialMobs.LOG.info("X={}, XO={}", target.getX(), target.xo); - SpecialMobs.LOG.info("Z={}, ZO={}", target.getZ(), target.zo); - - if (target.getX() != target.xo || target.getY() != target.yo || target.getZ() != target.zo) { + SpecialMobs.LOG.info( "X={}, XO={}", target.getX(), target.xo ); + SpecialMobs.LOG.info( "Z={}, ZO={}", target.getZ(), target.zo ); + + if( target.getX() != target.xo || target.getY() != target.yo || target.getZ() != target.zo ) { explode(); } else { - playSound(SoundEvents.FIRE_EXTINGUISH, 1.0F, 1.0F); + playSound( SoundEvents.FIRE_EXTINGUISH, 1.0F, 1.0F ); remove(); } } else { - target.hurt(DamageSource.fireball(this, owner), 6.0F); - - if (owner instanceof LivingEntity) { - doEnchantDamageEffects((LivingEntity) owner, target); + target.hurt( DamageSource.fireball( this, owner ), 6.0F ); + + if( owner instanceof LivingEntity ) { + doEnchantDamageEffects( (LivingEntity) owner, target ); } } } } - + @Override - public boolean hurt(DamageSource damageSource, float damage) { - if (!isCorporeal()) { - if (isInvulnerableTo(damageSource) || damageSource.isFire()) { + public boolean hurt( DamageSource damageSource, float damage ) { + if( !isCorporeal() ) { + if( isInvulnerableTo( damageSource ) || damageSource.isFire() ) { return false; } shouldExplode = true; return true; } else { - return super.hurt(damageSource, damage); + return super.hurt( damageSource, damage ); } } - + @Override - public void addAdditionalSaveData(CompoundNBT compoundNBT) { - super.addAdditionalSaveData(compoundNBT); - compoundNBT.putInt("ExplosionPower", explosionPower); - compoundNBT.putBoolean("Corporeal", isCorporeal()); - compoundNBT.putInt("TargetId", target == null ? -1 : target.getId()); + public void addAdditionalSaveData( CompoundNBT compoundNBT ) { + super.addAdditionalSaveData( compoundNBT ); + compoundNBT.putInt( "ExplosionPower", explosionPower ); + compoundNBT.putBoolean( "Corporeal", isCorporeal() ); + compoundNBT.putInt( "TargetId", target == null ? -1 : target.getId() ); } - + @Override - public void readAdditionalSaveData(CompoundNBT compoundNBT) { - super.readAdditionalSaveData(compoundNBT); - if (compoundNBT.contains("ExplosionPower", Constants.NBT.TAG_ANY_NUMERIC)) { - explosionPower = compoundNBT.getInt("ExplosionPower"); + public void readAdditionalSaveData( CompoundNBT compoundNBT ) { + super.readAdditionalSaveData( compoundNBT ); + if( compoundNBT.contains( "ExplosionPower", Constants.NBT.TAG_ANY_NUMERIC ) ) { + explosionPower = compoundNBT.getInt( "ExplosionPower" ); } - entityData.set(CORPOREAL, compoundNBT.getBoolean("Corporeal")); - - if (compoundNBT.contains("TargetId", Constants.NBT.TAG_ANY_NUMERIC)) { - Entity entity = level.getEntity(compoundNBT.getInt("TargetId")); - - if (entity instanceof LivingEntity) { + entityData.set( CORPOREAL, compoundNBT.getBoolean( "Corporeal" ) ); + + if( compoundNBT.contains( "TargetId", Constants.NBT.TAG_ANY_NUMERIC ) ) { + Entity entity = level.getEntity( compoundNBT.getInt( "TargetId" ) ); + + if( entity instanceof LivingEntity ) { target = (LivingEntity) entity; } } } - + @Override public IPacket getAddEntityPacket() { - return NetworkHooks.getEntitySpawningPacket(this); + return NetworkHooks.getEntitySpawningPacket( this ); } -} +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/BlindingSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/BlindingSilverfishEntity.java index 9110707..b2cd3ec 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/BlindingSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/BlindingSilverfishEntity.java @@ -13,7 +13,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,9 +28,10 @@ public class BlindingSilverfishEntity extends _SpecialSilverfishEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000 ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).effectImmune( Effects.BLINDNESS ); } @SpecialMob.LanguageProvider @@ -49,14 +49,15 @@ public class BlindingSilverfishEntity extends _SpecialSilverfishEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BlindingSilverfishEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BlindingSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.BLINDNESS ); - xpReward += 1; - } + public BlindingSilverfishEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -69,12 +70,4 @@ public class BlindingSilverfishEntity extends _SpecialSilverfishEntity { livingTarget.removeEffect( Effects.NIGHT_VISION ); // Prevent blind + night vision combo (black screen) } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "blinding" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FishingSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FishingSilverfishEntity.java index f91be8c..ae2c0fb 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FishingSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FishingSilverfishEntity.java @@ -3,19 +3,17 @@ package fathertoast.specialmobs.common.entity.silverfish; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SilverfishSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.ai.IAngler; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder; import fathertoast.specialmobs.datagen.loot.LootPoolBuilder; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -31,18 +29,19 @@ public class FishingSilverfishEntity extends _SpecialSilverfishEntity implements public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.5F, 0.4F ); - return new BestiaryInfo( 0x2D41F4 ); - //TODO theme - fishing + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x2D41F4 ).theme( BestiaryInfo.Theme.FISHING ) + .uniqueTextureBaseOnly() + .size( 1.2F, 0.5F, 0.4F ) + .addExperience( 2 ).drownImmune().fluidPushImmune() + .spitAttack( 0.0, 1.0, 40, 40, 10.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.9 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSilverfishEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.9 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SilverfishSpeciesConfig( species, 1.0 ); } @SpecialMob.LanguageProvider @@ -62,36 +61,22 @@ public class FishingSilverfishEntity extends _SpecialSilverfishEntity implements @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FishingSilverfishEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FishingSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - getSpecialData().setCanBreatheInWater( true ); - getSpecialData().setIgnoreWaterPush( true ); - xpReward += 2; - } + public FishingSilverfishEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 0.7F; - getSpecialData().rangedAttackCooldown = 32; - getSpecialData().rangedAttackMaxCooldown = 48; - getSpecialData().rangedAttackMaxRange = 10.0F; - //TODO add angler AI @ 4 } - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fishing" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- IAngler Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FlyingSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FlyingSilverfishEntity.java index dfaf187..4e3c9fb 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FlyingSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/FlyingSilverfishEntity.java @@ -4,16 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.ai.goal.SpecialLeapAtTargetGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,16 +25,11 @@ public class FlyingSilverfishEntity extends _SpecialSilverfishEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x6388B2 ); - //TODO theme - mountain - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSilverfishEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x6388B2 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).fallImmune().disableRangedAttack() + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -56,29 +47,20 @@ public class FlyingSilverfishEntity extends _SpecialSilverfishEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FlyingSilverfishEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FlyingSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - xpReward += 2; - } + public FlyingSilverfishEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackMaxRange = 0.0F; - goalSelector.addGoal( 3, new SpecialLeapAtTargetGoal( this, 10, 6.0F, 12.0F, 2.0F, 2.0F ) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "flying" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/PoisonSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/PoisonSilverfishEntity.java index 06dbb53..085deca 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/PoisonSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/PoisonSilverfishEntity.java @@ -13,7 +13,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,9 +28,10 @@ public class PoisonSilverfishEntity extends _SpecialSilverfishEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x779C68 ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x779C68 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).effectImmune( Effects.POISON ); } @SpecialMob.LanguageProvider @@ -49,14 +49,15 @@ public class PoisonSilverfishEntity extends _SpecialSilverfishEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PoisonSilverfishEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PoisonSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.POISON ); - xpReward += 1; - } + public PoisonSilverfishEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -68,12 +69,4 @@ public class PoisonSilverfishEntity extends _SpecialSilverfishEntity { livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "poison" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/ToughSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/ToughSilverfishEntity.java index 9b6ac10..ddb371e 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/ToughSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/ToughSilverfishEntity.java @@ -3,16 +3,12 @@ package fathertoast.specialmobs.common.entity.silverfish; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,19 +24,14 @@ public class ToughSilverfishEntity extends _SpecialSilverfishEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.6F, 0.45F ); - return new BestiaryInfo( 0xDD0E0E, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSilverfishEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 16.0 ) - .addAttribute( Attributes.ARMOR, 15.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.7 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDD0E0E ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithEyes() + .size( 1.5F, 0.6F, 0.45F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 16.0 ).addToAttribute( Attributes.ARMOR, 15.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 1.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.7 ); } @SpecialMob.LanguageProvider @@ -59,27 +50,13 @@ public class ToughSilverfishEntity extends _SpecialSilverfishEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return ToughSilverfishEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public ToughSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 1.0F; - } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "tough" ), - GET_TEXTURE_PATH( "tough_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public ToughSilverfishEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/_SpecialSilverfishEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/_SpecialSilverfishEntity.java index 4d40a27..bb438d9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/silverfish/_SpecialSilverfishEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/silverfish/_SpecialSilverfishEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.silverfish; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SilverfishSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.entity.ai.AIHelper; @@ -24,7 +25,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.IServerWorld; @@ -45,15 +45,26 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci public static MobFamily.Species<_SpecialSilverfishEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x303030 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x303030 ) + .vanillaTextureBaseOnly( "textures/entity/silverfish.png" ) + .experience( 5 ) + .spitAttack( 1.0, 1.3, 40, 40, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return SilverfishEntity.createAttributes(); + protected static final double DEFAULT_SPIT_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SilverfishSpeciesConfig( species, DEFAULT_SPIT_CHANCE ); } + /** @return This entity's species config. */ + public SilverfishSpeciesConfig getConfig() { return (SilverfishSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return SilverfishEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Silverfish", @@ -71,21 +82,12 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci //--------------- Variant-Specific Breakouts ---------------- - public _SpecialSilverfishEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); AIHelper.replaceHurtByTarget( this, new SpecialHurtByTargetGoal( this, SilverfishEntity.class ).setAlertOthers() ); - getSpecialData().rangedAttackDamage = 1.0F; - getSpecialData().rangedAttackCooldown = 40; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 10.0F; registerVariantGoals(); } @@ -114,11 +116,18 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialSilverfishEntity.class, DataSerializers.FLOAT ); + public _SpecialSilverfishEntity( EntityType entityType, World world ) { + super( entityType, world ); + if( !getConfig().SILVERFISH.spitterChance.rollChance( random ) ) getSpecialData().disableRangedAttack(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ @@ -127,9 +136,11 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - // TODO ranged attack + final double aggressiveChance = getConfig().SILVERFISH.aggressiveChance.get() < 0.0 ? + MobFamily.SILVERFISH.config.SILVERFISH.familyAggressiveChance.get() : + getConfig().SILVERFISH.aggressiveChance.get(); - if( random.nextFloat() < 0.05 ) { //TODO config + if( random.nextDouble() < aggressiveChance ) { // Immediately start calling for reinforcements if it can find a player if( getTarget() == null ) { final double followRange = getAttributeValue( Attributes.FOLLOW_RANGE ); @@ -160,6 +171,11 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci @Override public SpecialMobData<_SpecialSilverfishEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -168,16 +184,6 @@ public class _SpecialSilverfishEntity extends SilverfishEntity implements ISpeci @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "silverfish/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/silverfish.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/BruteSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/BruteSkeletonEntity.java index ecf738a..fbf1e01 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/BruteSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/BruteSkeletonEntity.java @@ -4,14 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; @@ -19,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -35,17 +32,12 @@ public class BruteSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.7F, 2.4F ); - return new BestiaryInfo( 0xFFF87E ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ) + .uniqueTextureWithOverlay() + .size( 1.2F, 0.7F, 2.4F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ); } @SpecialMob.LanguageProvider @@ -64,14 +56,15 @@ public class BruteSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BruteSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BruteSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - xpReward += 2; - } + public BruteSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -89,14 +82,4 @@ public class BruteSkeletonEntity extends _SpecialSkeletonEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "brute" ), - null, - GET_TEXTURE_PATH( "brute_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/FireSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/FireSkeletonEntity.java index 3c965b6..5c9eb5f 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/FireSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/FireSkeletonEntity.java @@ -8,11 +8,9 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,10 +26,10 @@ public class FireSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xDC1A00 ); - //TODO theme - fire + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDC1A00 ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureWithEyes() + .addExperience( 1 ).fireImmune().waterSensitive(); } @SpecialMob.LanguageProvider @@ -50,14 +48,15 @@ public class FireSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FireSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FireSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setDamagedByWater( true ); - xpReward += 1; - } + public FireSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -71,13 +70,4 @@ public class FireSkeletonEntity extends _SpecialSkeletonEntity { arrow.setSecondsOnFire( 100 ); return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fire" ), - GET_TEXTURE_PATH( "fire_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GatlingSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GatlingSkeletonEntity.java index be7474e..a456203 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GatlingSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GatlingSkeletonEntity.java @@ -3,16 +3,14 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,16 +26,18 @@ public class GatlingSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFFFF0B ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFFF0B ) + .uniqueOverlayTexture() + .addExperience( 2 ) + .multiplyRangedSpread( 2.0 ).multiplyRangedWalkSpeed( 0.3 ).rangedCooldown( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0F, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -56,32 +56,13 @@ public class GatlingSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GatlingSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public GatlingSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - setRangedAI( 0.3, 1 ); - getSpecialData().rangedAttackSpread *= 2.0F; - } - - /** Override to change this entity's chance to spawn with a melee weapon. */ - @Override - protected double getVariantMeleeChance() { return 0.0; } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/skeleton/skeleton.png" ), - null, - GET_TEXTURE_PATH( "gatling_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public GatlingSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GiantSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GiantSkeletonEntity.java index 0da9ca1..e6a6d9e 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GiantSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/GiantSkeletonEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,17 +24,12 @@ public class GiantSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.99F ); - return new BestiaryInfo( 0x494949 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x494949 ) + .size( 1.5F, 0.9F, 2.99F ) + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 2.0 ); } @SpecialMob.LanguageProvider @@ -55,20 +47,17 @@ public class GiantSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GiantSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public GiantSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); maxUpStep = 1.0F; - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; } /** Sets this entity as a baby. */ diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/KnightSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/KnightSkeletonEntity.java index be98c1c..8635c42 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/KnightSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/KnightSkeletonEntity.java @@ -3,13 +3,12 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -30,17 +29,17 @@ public class KnightSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDDDDDD ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDDDDDD ) + .addExperience( 2 ).multiplyRangedSpread( 1.2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 4.0 ).addToRangedDamage( 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 0.05, 1.0 ); } @SpecialMob.LanguageProvider @@ -58,36 +57,24 @@ public class KnightSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return KnightSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public KnightSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 4.0F; - getSpecialData().rangedAttackSpread *= 1.2F; - } + public KnightSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < 0.95 ) { - setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.IRON_SWORD ) ); - setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); - } + setItemSlot( EquipmentSlotType.HEAD, new ItemStack( Items.IRON_HELMET ) ); setItemSlot( EquipmentSlotType.CHEST, new ItemStack( Items.IRON_CHESTPLATE ) ); setItemSlot( EquipmentSlotType.LEGS, new ItemStack( Items.IRON_LEGGINGS ) ); setItemSlot( EquipmentSlotType.FEET, new ItemStack( Items.IRON_BOOTS ) ); } - - /** Override to change this entity's chance to spawn with a melee weapon. */ - @Override - protected double getVariantMeleeChance() { return 0.0; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/NinjaSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/NinjaSkeletonEntity.java index 0998c8c..485bff3 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/NinjaSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/NinjaSkeletonEntity.java @@ -3,10 +3,11 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.ai.INinja; import fathertoast.specialmobs.common.entity.ai.goal.NinjaGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -15,7 +16,6 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.datasync.DataParameter; @@ -23,7 +23,10 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.*; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.DamageSource; +import net.minecraft.util.Hand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; @@ -44,15 +47,17 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x333366 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x333366 ) + .uniqueOverlayTexture() + .addExperience( 2 ).pressurePlateImmune() + .multiplyRangedCooldown( 0.5F ).rangedMaxRange( 9.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 0.5, 0.0 ); } @SpecialMob.LanguageProvider @@ -71,18 +76,19 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return NinjaSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public NinjaSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public NinjaSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - setRangedAI( 1.0, 10, 9.0F ); goalSelector.addGoal( -9, new NinjaGoal<>( this ) ); } @@ -93,10 +99,6 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj setCanPickUpLoot( true ); } - /** Override to change this entity's chance to spawn with a melee weapon. */ - @Override - protected double getVariantMeleeChance() { return 0.5; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { revealTo( target, true ); } @@ -157,21 +159,15 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj /** Sets this entity's movement. */ @Override - public void setDeltaMovement( Vector3d vec ) { - if( !isCrouchingTiger() ) super.setDeltaMovement( vec ); - } + public void setDeltaMovement( Vector3d vec ) { if( !isCrouchingTiger() ) super.setDeltaMovement( vec ); } /** Returns true if this entity should push and be pushed by other entities when colliding. */ @Override - public boolean isPushable() { - return super.isPushable() && !isCrouchingTiger(); - } + public boolean isPushable() { return super.isPushable() && !isCrouchingTiger(); } /** Sets this entity on fire for a specific duration. */ @Override - public void setRemainingFireTicks( int ticks ) { - if( !isCrouchingTiger() ) super.setRemainingFireTicks( ticks ); - } + public void setRemainingFireTicks( int ticks ) { if( !isCrouchingTiger() ) super.setRemainingFireTicks( ticks ); } /** Reveals this ninja and sets its target so that it doesn't immediately re-disguise itself. */ public void revealTo( @Nullable Entity target, boolean ambush ) { @@ -193,16 +189,6 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj } } - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/skeleton/skeleton.png" ), - null, - GET_TEXTURE_PATH( "ninja_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- INinja Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/PoisonSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/PoisonSkeletonEntity.java index 8bbaa14..05cd388 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/PoisonSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/PoisonSkeletonEntity.java @@ -18,7 +18,6 @@ import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -34,9 +33,10 @@ public class PoisonSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x779C68 ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x779C68 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithOverlay() + .addExperience( 1 ); } @SpecialMob.LanguageProvider @@ -54,14 +54,15 @@ public class PoisonSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PoisonSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PoisonSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.POISON ); - xpReward += 1; - } + public PoisonSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -84,14 +85,4 @@ public class PoisonSkeletonEntity extends _SpecialSkeletonEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "poison" ), - null, - GET_TEXTURE_PATH( "poison_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SniperSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SniperSkeletonEntity.java index aba7e4e..50b6bed 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SniperSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SniperSkeletonEntity.java @@ -3,16 +3,14 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,16 +26,18 @@ public class SniperSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x486720 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x486720 ) + .uniqueTextureWithOverlay() + .addExperience( 1 ) + .multiplyRangedSpread( 0.05 ).multiplyRangedWalkSpeed( 0.3 ).multiplyRangedCooldown( 1.5F ).rangedMaxRange( 25.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 4.0 ) + .addToAttribute( Attributes.FOLLOW_RANGE, 16.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.FOLLOW_RANGE, 16.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -56,33 +56,13 @@ public class SniperSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SniperSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public SniperSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - setRangedAI( 0.3, 30, 25.0F ); - getSpecialData().rangedAttackDamage += 2.0F; - getSpecialData().rangedAttackSpread *= 0.05F; - } - - /** Override to change this entity's chance to spawn with a melee weapon. */ - @Override - protected double getVariantMeleeChance() { return 0.0; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "sniper" ), - null, - GET_TEXTURE_PATH( "sniper_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public SniperSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SpitfireSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SpitfireSkeletonEntity.java index 208c296..80af62a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SpitfireSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/SpitfireSkeletonEntity.java @@ -3,18 +3,17 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.SmallFireballEntity; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -31,18 +30,18 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.99F ).fireImmune(); - return new BestiaryInfo( 0xDC1A00, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - fire + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDC1A00 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureWithEyes() + .size( 1.5F, 0.9F, 2.99F ) + .addExperience( 2 ).fireImmune().waterSensitive().rangedDamage( 0.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0F, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -60,27 +59,19 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SpitfireSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public SpitfireSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - getSpecialData().setDamagedByWater( true ); maxUpStep = 1.0F; - xpReward += 2; } - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; - } - - /** Override to change this entity's chance to spawn with a melee weapon. */ - @Override - protected double getVariantMeleeChance() { return 0.0; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -92,7 +83,7 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity { public void performRangedAttack( LivingEntity target, float damageMulti ) { if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 ); - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); for( int i = 0; i < 3; i++ ) { final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance; @@ -112,13 +103,4 @@ public class SpitfireSkeletonEntity extends _SpecialSkeletonEntity { /** @return True if this entity is a baby. */ @Override public boolean isBaby() { return false; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fire" ), - GET_TEXTURE_PATH( "fire_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/StraySkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/StraySkeletonEntity.java index 2297f28..615f8d9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/StraySkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/StraySkeletonEntity.java @@ -18,7 +18,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; @@ -36,15 +35,14 @@ public class StraySkeletonEntity extends _SpecialSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDDEAEA, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - ice + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDDEAEA ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.ICE ) + .vanillaTextureWithOverlay( "textures/entity/skeleton/stray.png", "textures/entity/skeleton/stray_overlay.png" ) + .addExperience( 1 ).effectImmune( Effects.MOVEMENT_SLOWDOWN ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return StrayEntity.createAttributes(); - } + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return StrayEntity.createAttributes(); } @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { @@ -60,13 +58,15 @@ public class StraySkeletonEntity extends _SpecialSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return StraySkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public StraySkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public StraySkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -90,16 +90,6 @@ public class StraySkeletonEntity extends _SpecialSkeletonEntity { return arrow; } - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/skeleton/stray.png" ), - null, - new ResourceLocation( "textures/entity/skeleton/stray_overlay.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- Stray Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java index 006b9e7..f8e4bf2 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.skeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.SpecialMobData; @@ -12,7 +13,6 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; @@ -36,7 +36,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; @@ -47,7 +46,6 @@ import net.minecraft.world.World; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.UUID; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -60,15 +58,27 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS public static MobFamily.Species<_SpecialSkeletonEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x494949 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x494949 ) + .vanillaTextureBaseOnly( "textures/entity/skeleton/skeleton.png" ) + .experience( 5 ).undead() + .bowAttack( 2.0, 1.0, 1.0, 20, 15.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return SkeletonEntity.createAttributes(); + protected static final double DEFAULT_BOW_CHANCE = 0.95; + protected static final double DEFAULT_SHIELD_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, DEFAULT_BOW_CHANCE, DEFAULT_SHIELD_CHANCE ); } + /** @return This entity's species config. */ + public SkeletonSpeciesConfig getConfig() { return (SkeletonSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return SkeletonEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Skeleton", @@ -86,57 +96,19 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS //--------------- Variant-Specific Breakouts ---------------- - public _SpecialSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); - - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedAttackCooldown = 20; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 15.0F; registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { setRangedAI( 1.0, 20, 0.0F ); } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime ) { - getSpecialData().rangedWalkSpeed = (float) walkSpeed; - getSpecialData().rangedAttackCooldown = cooldownTime; - getSpecialData().rangedAttackMaxCooldown = cooldownTime; - } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime, float range ) { - setRangedAI( walkSpeed, cooldownTime ); - getSpecialData().rangedAttackMaxRange = range; - } - /** Override to change this entity's attack goal priority. */ protected int getVariantAttackPriority() { return 4; } - /** Called during spawn finalization to set starting equipment. */ - @Override - protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { - super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < getVariantMeleeChance() ) { //TODO config the default 5% chance - setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.IRON_SWORD ) ); - } - } - - /** Override to change this entity's chance to spawn with a melee weapon. */ - protected double getVariantMeleeChance() { return getSpecialData().rangedAttackMaxRange > 0.0F ? 0.05 : 1.0; } - /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { @@ -151,7 +123,7 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS final double dZ = target.getZ() - getZ(); final double dH = MathHelper.sqrt( dX * dX + dZ * dZ ); arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F, - getSpecialData().rangedAttackSpread * (14 - 4 * level.getDifficulty().getId()) ); + getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) ); playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) ); level.addFreshEntity( arrow ); @@ -160,7 +132,7 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS /** @return The arrow for this skeleton to shoot. */ @Override protected AbstractArrowEntity getArrow( ItemStack arrowItem, float damageMulti ) { - return getVariantArrow( super.getArrow( arrowItem, damageMulti * getSpecialData().rangedAttackDamage ), + return getVariantArrow( super.getArrow( arrowItem, damageMulti * getSpecialData().getRangedAttackDamage() ), arrowItem, damageMulti ); } @@ -194,11 +166,16 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS /** This entity's attack AI. */ private Goal currentAttackAI; + public _SpecialSkeletonEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); entityData.define( IS_BABY, false ); } @@ -207,10 +184,26 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - setBaby( random.nextDouble() < 0.05 ); //TODO config + + setBaby( MobFamily.SKELETON.config.SKELETONS.babyChance.rollChance( random ) ); + return groupData; } + /** Called during spawn finalization to set starting equipment. */ + @Override + protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { + super.populateDefaultEquipmentSlots( difficulty ); + + if( getSpecialData().getRangedAttackMaxRange() <= 0.0F || !getConfig().SKELETONS.bowEquipChance.rollChance( random ) ) { + setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.IRON_SWORD ) ); + + if( getConfig().SKELETONS.shieldEquipChance.rollChance( random ) ) { + setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); + } + } + } + /** Called to set this entity's attack AI based on current equipment. */ @Override public void reassessWeaponGoal() { @@ -220,9 +213,9 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS final SpecialMobData<_SpecialSkeletonEntity> data = getSpecialData(); final ItemStack weapon = getItemInHand( ProjectileHelper.getWeaponHoldingHand( this, item -> item instanceof BowItem ) ); - if( data.rangedAttackMaxRange > 0.0F && weapon.getItem() == Items.BOW ) { - currentAttackAI = new RangedBowAttackGoal<>( this, data.rangedWalkSpeed, - data.rangedAttackCooldown, data.rangedAttackMaxRange ); + if( data.getRangedAttackMaxRange() > 0.0F && weapon.getItem() == Items.BOW ) { + currentAttackAI = new RangedBowAttackGoal<>( this, data.getRangedWalkSpeed(), + data.getRangedAttackCooldown(), data.getRangedAttackMaxRange() ); } else { currentAttackAI = new MeleeAttackGoal( this, 1.2, false ); @@ -271,9 +264,6 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS /** The parameter for baby status. */ private static final DataParameter IS_BABY = EntityDataManager.defineId( _SpecialSkeletonEntity.class, DataSerializers.BOOLEAN ); - /** The speed boost to apply when in baby state. */ - private static final AttributeModifier BABY_SPEED_BOOST = new AttributeModifier( UUID.fromString( "B9766B59-9566-4402-BC1F-2EE2A276D836" ), - "Baby speed boost", 0.5, AttributeModifier.Operation.MULTIPLY_BASE ); /** Sets this entity as a baby. */ @Override @@ -282,9 +272,9 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS if( level != null && !level.isClientSide ) { final ModifiableAttributeInstance attributeInstance = getAttribute( Attributes.MOVEMENT_SPEED ); //noinspection ConstantConditions - attributeInstance.removeModifier( BABY_SPEED_BOOST ); + attributeInstance.removeModifier( References.BABY_SPEED_BOOST ); if( value ) { - attributeInstance.addTransientModifier( BABY_SPEED_BOOST ); + attributeInstance.addTransientModifier( References.BABY_SPEED_BOOST ); } } } @@ -324,6 +314,11 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS @Override public SpecialMobData<_SpecialSkeletonEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -332,16 +327,6 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "skeleton/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/skeleton/skeleton.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/BlackberrySlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/BlackberrySlimeEntity.java index 1456018..4decc8a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/BlackberrySlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/BlackberrySlimeEntity.java @@ -3,15 +3,15 @@ package fathertoast.specialmobs.common.entity.slime; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.entity.ai.IExplodingMob; +import fathertoast.specialmobs.common.entity.ai.goal.SpecialSwellGoal; import fathertoast.specialmobs.common.util.ExplosionHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.AreaEffectCloudEntity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -21,19 +21,17 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.potion.EffectInstance; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @SpecialMob -public class BlackberrySlimeEntity extends _SpecialSlimeEntity { +public class BlackberrySlimeEntity extends _SpecialSlimeEntity implements IExplodingMob { //--------------- Static Special Mob Hooks ---------------- @@ -41,8 +39,11 @@ public class BlackberrySlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x331133 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x331133 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 2.0 ); } @SpecialMob.LanguageProvider @@ -61,39 +62,34 @@ public class BlackberrySlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BlackberrySlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BlackberrySlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - slimeExperienceValue += 2; - } - private static final byte MAX_FUSE = 30; private int fuse = 0; - private int swellDir = 0; private boolean ignited = false; - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size ); - } + public BlackberrySlimeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - goalSelector.addGoal( 0, new SlimeSwellGoal( this ) ); + goalSelector.addGoal( 0, new SpecialSwellGoal<>( this ) ); } /** Called each tick to update this entity. */ @Override public void tick() { if( isAlive() && !level.isClientSide() ) { - if( ignited ) swellDir = 1; + if( ignited ) setSwellDir( 1 ); - if( swellDir > 0 ) { + if( getSwellDir() > 0 ) { if( fuse == 0 ) { playSound( SoundEvents.CREEPER_PRIMED, 1.0F, 0.5F ); } @@ -107,9 +103,9 @@ public class BlackberrySlimeEntity extends _SpecialSlimeEntity { changeFuse( +1 ); } } - else if( swellDir < 0 && fuse > 0 ) { + else if( getSwellDir() < 0 && fuse > 0 ) { changeFuse( -1 ); - if( fuse <= 0 ) swellDir = 0; + if( fuse <= 0 ) setSwellDir( 0 ); } } super.tick(); @@ -188,51 +184,20 @@ public class BlackberrySlimeEntity extends _SpecialSlimeEntity { @Override protected IParticleData getParticleType() { return ParticleTypes.SMOKE; } - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "blackberry" ) - }; - /** @return All default textures for this entity. */ + //--------------- IExplodingEntity Implementations ---------------- + + private int swellDir = 0; + + /** Sets this exploding entity's swell direction. */ @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public void setSwellDir( int value ) { swellDir = value; } + /** @return This exploding entity's swell direction. */ + @Override + public int getSwellDir() { return swellDir; } - //--------------- Nested Classes ---------------- - - /** The "creeper swell" goal repurposed for use on a slime. */ - private static class SlimeSwellGoal extends Goal { - - private final BlackberrySlimeEntity slime; - - private LivingEntity target; - - public SlimeSwellGoal( BlackberrySlimeEntity entity ) { - slime = entity; - setFlags( EnumSet.of( Flag.MOVE ) ); - } - - public boolean canUse() { - final LivingEntity target = slime.getTarget(); - return slime.swellDir > 0 || target != null && slime.distanceToSqr( target ) < 9.0F + (slime.getSize() - 1) * 2.0F; - } - - public void start() { - slime.getNavigation().stop(); - target = slime.getTarget(); - } - - public void stop() { - slime.swellDir = -1; - target = null; - } - - public void tick() { - if( target == null || slime.distanceToSqr( target ) > 49.0 || !slime.getSensing().canSee( target ) ) { - slime.swellDir = -1; - } - else { - slime.swellDir = 1; - } - } - } + /** @return Additional range from its target at which this entity will start to explode. */ + @Override + public double getExtraRange() { return (getSize() - 1) * 2.0F; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/BlueberrySlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/BlueberrySlimeEntity.java index 828b4fb..6942f16 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/BlueberrySlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/BlueberrySlimeEntity.java @@ -10,7 +10,6 @@ import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.fluid.Fluid; import net.minecraft.item.Items; @@ -20,7 +19,6 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.pathfinding.PathNavigator; import net.minecraft.pathfinding.PathNodeType; import net.minecraft.tags.FluidTags; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -36,9 +34,11 @@ public class BlueberrySlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x766BBC ); - //TODO theme - water + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x766BBC ).theme( BestiaryInfo.Theme.WATER ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).drownImmune().fluidPushImmune() + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ); } @SpecialMob.LanguageProvider @@ -57,24 +57,19 @@ public class BlueberrySlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BlueberrySlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public BlueberrySlimeEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setCanBreatheInWater( true ); - getSpecialData().setIgnoreWaterPush( true ); - slimeExperienceValue += 1; - setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() ); } - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.ATTACK_DAMAGE, 1.0 * size ); - } - /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { AIHelper.removeGoals( goalSelector, 1 ); // SlimeEntity.FloatGoal @@ -113,12 +108,4 @@ public class BlueberrySlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return ParticleTypes.SPLASH; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "blueberry" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/CaramelSlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/CaramelSlimeEntity.java index 9c6ca13..1583ad3 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/CaramelSlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/CaramelSlimeEntity.java @@ -15,7 +15,6 @@ import net.minecraft.particles.IParticleData; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -32,8 +31,11 @@ public class CaramelSlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x9D733F ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x9D733F ) + .uniqueTextureBaseOnly() + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 8.0 ); } @SpecialMob.LanguageProvider @@ -52,23 +54,19 @@ public class CaramelSlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return CaramelSlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public CaramelSlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - slimeExperienceValue += 2; - } - private final DamageSource grabDamageSource = DamageSource.mobAttack( this ).bypassArmor().bypassMagic(); private int grabTime; - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 4.0 * size ); - } + public CaramelSlimeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -100,12 +98,4 @@ public class CaramelSlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return JUMP_PARTICLE; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "caramel" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/GrapeSlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/GrapeSlimeEntity.java index 11c79b7..b97ca0a 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/GrapeSlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/GrapeSlimeEntity.java @@ -8,13 +8,11 @@ import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -30,9 +28,12 @@ public class GrapeSlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xB333B3 ); - //TODO theme - mountain + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xB333B3 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fallImmune() + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -51,21 +52,15 @@ public class GrapeSlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GrapeSlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public GrapeSlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - slimeExperienceValue += 1; - } - - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 4.0 * size ); - multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); - } + public GrapeSlimeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -79,12 +74,4 @@ public class GrapeSlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return JUMP_PARTICLE; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "grape" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/LemonSlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/LemonSlimeEntity.java index 17e12e6..87dd55c 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/LemonSlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/LemonSlimeEntity.java @@ -16,7 +16,6 @@ import net.minecraft.item.Items; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; @@ -34,9 +33,11 @@ public class LemonSlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xE6E861 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE6E861 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).fireImmune() + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ); } @SpecialMob.LanguageProvider @@ -55,19 +56,15 @@ public class LemonSlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return LemonSlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public LemonSlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - slimeExperienceValue += 2; - } - - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size ); - } + public LemonSlimeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -93,12 +90,4 @@ public class LemonSlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return JUMP_PARTICLE; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "lemon" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/StrawberrySlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/StrawberrySlimeEntity.java index 143a8aa..f7a97ca 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/StrawberrySlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/StrawberrySlimeEntity.java @@ -11,7 +11,6 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.fluid.Fluid; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; @@ -20,7 +19,6 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.pathfinding.PathNavigator; import net.minecraft.pathfinding.PathNodeType; import net.minecraft.tags.FluidTags; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -36,10 +34,10 @@ public class StrawberrySlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xBE696B ); - //TODO theme - fire + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xBE696B ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fireImmune().waterSensitive(); } @SpecialMob.LanguageProvider @@ -58,14 +56,16 @@ public class StrawberrySlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return StrawberrySlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public StrawberrySlimeEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setDamagedByWater( true ); - slimeExperienceValue += 1; - setPathfindingMalus( PathNodeType.LAVA, PathNodeType.WALKABLE.getMalus() ); } @@ -106,12 +106,4 @@ public class StrawberrySlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return ParticleTypes.FLAME; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "strawberry" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/WatermelonSlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/WatermelonSlimeEntity.java index f3a89b4..140d928 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/WatermelonSlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/WatermelonSlimeEntity.java @@ -15,7 +15,6 @@ import net.minecraft.item.Items; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -32,9 +31,13 @@ public class WatermelonSlimeEntity extends _SpecialSlimeEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 3.06F, 3.06F ); - return new BestiaryInfo( 0xDF7679, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDF7679 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureBaseOnly() + .size( 1.5F, 3.06F, 3.06F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 8.0 ).addToAttribute( Attributes.ARMOR, 16.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 1.0 ); } @SpecialMob.LanguageProvider @@ -54,21 +57,15 @@ public class WatermelonSlimeEntity extends _SpecialSlimeEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WatermelonSlimeEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public WatermelonSlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - slimeExperienceValue += 2; - } - - /** Override to modify this slime's base attributes by size. */ - @Override - protected void modifyVariantAttributes( int size ) { - addAttribute( Attributes.MAX_HEALTH, 2.0 * size + 8.0 ); - setAttribute( Attributes.ARMOR, 15.0 ); - } + public WatermelonSlimeEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override @@ -97,12 +94,4 @@ public class WatermelonSlimeEntity extends _SpecialSlimeEntity { /** @return This slime's particle type for jump effects. */ @Override protected IParticleData getParticleType() { return JUMP_PARTICLE; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "watermelon" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/slime/_SpecialSlimeEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/slime/_SpecialSlimeEntity.java index a1e9038..23d9443 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/slime/_SpecialSlimeEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/slime/_SpecialSlimeEntity.java @@ -3,7 +3,6 @@ package fathertoast.specialmobs.common.entity.slime; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.util.References; @@ -11,21 +10,19 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.AttributeModifierManager; import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.Attributes; -import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; import net.minecraft.entity.monster.MonsterEntity; import net.minecraft.entity.monster.SlimeEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.SnowballEntity; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -42,11 +39,13 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe public static MobFamily.Species<_SpecialSlimeEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x51A03E ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x51A03E ) + .vanillaTextureBaseOnly( "textures/entity/slime/slime.png" ) + .experience( 0 ); } - @SpecialMob.AttributeCreator + @SpecialMob.AttributeSupplier public static AttributeModifierMap.MutableAttribute createAttributes() { return MonsterEntity.createMonsterAttributes(); // Slimes define their attributes elsewhere based on size } @@ -68,14 +67,6 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe //--------------- Variant-Specific Breakouts ---------------- - public _SpecialSlimeEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - - /** Override to modify this slime's base attributes by size. */ - protected void modifyVariantAttributes( int size ) { } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -108,66 +99,45 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialSlimeEntity.class, DataSerializers.FLOAT ); - protected int slimeExperienceValue = 0; + /** Used to reset slimes' attributes to their freshly spawned state so attribute adjustments may be reapplied on size change. */ + private static ListNBT slimeAttributeSnapshot; + + private static ListNBT getAttributeSnapshot() { + if( slimeAttributeSnapshot == null ) + slimeAttributeSnapshot = new AttributeModifierManager( createAttributes().build() ).save(); + return slimeAttributeSnapshot; + } + + private int slimeExperienceValue; + + public _SpecialSlimeEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().initialize(); + } /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Returns true if this slime can deal damage. */ @Override - protected boolean isDealsDamage() { return getSize() > 0 && isEffectiveAi(); } // TODO config for allow tiny slimes to hit + protected boolean isDealsDamage() { + return MobFamily.SLIME.config.SLIMES.tinySlimesDealDamage.get() ? isEffectiveAi() : super.isDealsDamage(); + } /** Sets this slime's size, optionally resetting its health to max. */ @Override protected void setSize( int size, boolean resetHealth ) { + // We must reset all attributes and reapply changes since slimes set attribute base values on size change + getAttributes().load( getAttributeSnapshot() ); super.setSize( size, resetHealth ); + getSpecies().config.GENERAL.attributeChanges.apply( this ); - modifyVariantAttributes( size ); if( resetHealth ) setHealth( getMaxHealth() ); - xpReward = size + slimeExperienceValue; - } - - /** - * Alters this slime's base attribute by adding an amount to it. - * Do NOT use this for move speed, instead use {@link #multAttribute(Attribute, double)} - */ - protected void addAttribute( Attribute attribute, double amount ) { - if( attribute != Attributes.MAX_HEALTH && attribute != Attributes.ATTACK_DAMAGE && attribute != Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Slime relative attributes are only health, damage, and speed!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() + amount ); - } - - /** - * Alters this slime's base attribute by multiplying it by an amount. - * Mainly use this for move speed, for other attributes use {@link #addAttribute(Attribute, double)} - */ - protected void multAttribute( Attribute attribute, double amount ) { - if( attribute != Attributes.MAX_HEALTH && attribute != Attributes.ATTACK_DAMAGE && attribute != Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Slime relative attributes are only health, damage, and speed!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() * amount ); - } - - /** Sets this slime's base attribute. */ - protected void setAttribute( Attribute attribute, double amount ) { - if( attribute == Attributes.MAX_HEALTH || attribute == Attributes.ATTACK_DAMAGE || attribute == Attributes.MOVEMENT_SPEED ) - throw new IllegalArgumentException( "Use slime relative attribute!" ); - - final ModifiableAttributeInstance attributeInstance = getAttribute( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( amount ); + setExperience( getExperience() ); // Update for new size } @@ -179,6 +149,11 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe @Override public SpecialMobData<_SpecialSlimeEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return slimeExperienceValue; } // Slime base xp @@ -190,18 +165,6 @@ public class _SpecialSlimeEntity extends SlimeEntity implements ISpecialMob<_Spe xpReward = getSize() + xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "slime/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/slime/slime.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/BabySpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/BabySpiderEntity.java index a7cd333..5fdfc70 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/BabySpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/BabySpiderEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,18 +24,13 @@ public class BabySpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.6F, 0.4F ); - return new BestiaryInfo( 0xFFC0CB, BestiaryInfo.BaseWeight.DISABLED ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .multAttribute( Attributes.MAX_HEALTH, 0.25 ) - .addAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFC0CB ).weight( BestiaryInfo.DefaultWeight.DISABLED ) + .size( 0.4F, 0.6F, 0.4F ) + .experience( 1 ).disableRangedAttack() + .multiplyAttribute( Attributes.MAX_HEALTH, 0.25 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -55,19 +47,13 @@ public class BabySpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BabySpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BabySpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.4F ); - xpReward = 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage -= 1.0F; - getSpecialData().rangedAttackMaxRange = 0.0F; - } + public BabySpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/DesertSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/DesertSpiderEntity.java index b646596..a70be76 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/DesertSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/DesertSpiderEntity.java @@ -3,20 +3,18 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.Config; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -32,17 +30,12 @@ public class DesertSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.95F, 0.7F ); - return new BestiaryInfo( 0xE6DDAC ); - //TODO theme - desert - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 4.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE6DDAC ).theme( BestiaryInfo.Theme.DESERT ) + .uniqueTextureWithEyes() + .size( 0.8F, 0.95F, 0.7F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ); } @SpecialMob.LanguageProvider @@ -60,14 +53,15 @@ public class DesertSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DesertSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public DesertSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 0.8F ); - xpReward += 2; - } + public DesertSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -76,7 +70,7 @@ public class DesertSpiderEntity extends _SpecialSpiderEntity { final LivingEntity livingTarget = (LivingEntity) target; final int duration = MobHelper.getDebuffDuration( level.getDifficulty() ); - if( true ) { //TODO config + if( Config.MAIN.GENERAL.enableNausea.get() ) { livingTarget.addEffect( new EffectInstance( Effects.CONFUSION, duration, 0 ) ); } livingTarget.addEffect( new EffectInstance( Effects.BLINDNESS, duration, 0 ) ); @@ -85,13 +79,4 @@ public class DesertSpiderEntity extends _SpecialSpiderEntity { livingTarget.addEffect( new EffectInstance( Effects.DAMAGE_RESISTANCE, duration, -3 ) ); // 40% inc damage taken } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "desert" ), - GET_TEXTURE_PATH( "desert_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/FlyingSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/FlyingSpiderEntity.java index d659754..686e828 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/FlyingSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/FlyingSpiderEntity.java @@ -4,16 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.ai.goal.SpecialLeapAtTargetGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,16 +25,11 @@ public class FlyingSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x6388B2 ); - //TODO theme - mountain - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x6388B2 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureWithEyes() + .addExperience( 2 ).fallImmune().disableRangedAttack() + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -56,30 +47,20 @@ public class FlyingSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FlyingSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FlyingSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - xpReward += 2; - } + public FlyingSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackMaxRange = 0.0F; - goalSelector.addGoal( 3, new SpecialLeapAtTargetGoal( this, 10, 6.0F, 12.0F, 2.0F, 2.0F ) ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "flying" ), - GET_TEXTURE_PATH( "flying_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/GiantSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/GiantSpiderEntity.java index f24d9a2..1c815e8 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/GiantSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/GiantSpiderEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,17 +24,12 @@ public class GiantSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 1.9F, 1.3F ); - return new BestiaryInfo( 0xA80E0E ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 16.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA80E0E ) + .size( 1.5F, 1.9F, 1.3F ) + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 16.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 1.0 ); } @SpecialMob.LanguageProvider @@ -55,18 +47,13 @@ public class GiantSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GiantSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public GiantSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 1.0F; - } + public GiantSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java index 65697db..3fd6ada 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java @@ -4,15 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.AttributeModifier; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; import net.minecraft.entity.player.PlayerEntity; @@ -20,7 +17,6 @@ import net.minecraft.item.Food; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; import net.minecraftforge.event.ForgeEventFactory; @@ -39,17 +35,13 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 1.9F, 1.3F ); - return new BestiaryInfo( 0x799C65 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 4.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, -1.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x799C65 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureWithEyes() + .size( 1.5F, 1.9F, 1.3F ) + .addExperience( 2 ).regen( 40 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, -1.0 ); } @SpecialMob.LanguageProvider @@ -68,6 +60,11 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HungrySpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -83,19 +80,7 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity { /** The level of increased max health gained. */ private int maxHealthStacks; - public HungrySpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); - getSpecialData().setRegenerationTime( 40 ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage -= 1.0F; - getSpecialData().rangedAttackMaxRange = 0.0F; - } + public HungrySpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -153,13 +138,4 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity { growthLevel = saveTag.getByte( References.TAG_GROWTH_LEVEL ); updateFeedingLevels(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "hungry" ), - GET_TEXTURE_PATH( "hungry_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/MotherSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/MotherSpiderEntity.java index 86d5f2e..88edfb9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/MotherSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/MotherSpiderEntity.java @@ -3,20 +3,18 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.MotherSpiderSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.ILivingEntityData; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -35,20 +33,25 @@ public class MotherSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 1.7F, 1.0F ); - return new BestiaryInfo( 0xB300B3 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xB300B3 ) + .uniqueTextureWithEyes() + .size( 1.2F, 1.7F, 1.0F ) + .addExperience( 1 ).regen( 30 ) + .addToAttribute( Attributes.MAX_HEALTH, 16.0 ).addToAttribute( Attributes.ARMOR, 6.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 3.0 ).addToRangedDamage( 1.5 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 16.0 ) - .addAttribute( Attributes.ARMOR, 6.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 3.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new MotherSpiderSpeciesConfig( species, DEFAULT_SPIT_CHANCE, + 2, 4, 3, 6 ); } + /** @return This entity's species config. */ + @Override + public MotherSpiderSpeciesConfig getConfig() { return (MotherSpiderSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Mother Spider", @@ -64,28 +67,23 @@ public class MotherSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MotherSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public MotherSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - getSpecialData().setRegenerationTime( 30 ); - xpReward += 1; - - babies = 2 + random.nextInt( 3 ); - extraBabies = 3 + random.nextInt( 4 ); - } - /** The number of babies spawned on death. */ private int babies; /** The number of extra babies that can be spawned from hits. */ private int extraBabies; - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 1.5F; + public MotherSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + babies = getConfig().MOTHER.babies.next( random ); + extraBabies = getConfig().MOTHER.extraBabies.next( random ); } /** @return Attempts to damage this entity; returns true if the hit was successful. */ @@ -159,13 +157,4 @@ public class MotherSpiderEntity extends _SpecialSpiderEntity { if( saveTag.contains( References.TAG_EXTRA_BABIES, References.NBT_TYPE_NUMERICAL ) ) extraBabies = saveTag.getByte( References.TAG_EXTRA_BABIES ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "mother" ), - GET_TEXTURE_PATH( "mother_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/PaleSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/PaleSpiderEntity.java index 28093ca..12f02bd 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/PaleSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/PaleSpiderEntity.java @@ -4,19 +4,16 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -32,16 +29,11 @@ public class PaleSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDED4C6 ); - //TODO theme - ice - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.ARMOR, 15.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDED4C6 ).theme( BestiaryInfo.Theme.ICE ) + .uniqueTextureWithEyes() + .addExperience( 1 ) + .addToAttribute( Attributes.ARMOR, 15.0 ); } @SpecialMob.LanguageProvider @@ -59,13 +51,15 @@ public class PaleSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PaleSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PaleSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public PaleSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -78,13 +72,4 @@ public class PaleSpiderEntity extends _SpecialSpiderEntity { livingTarget.addEffect( new EffectInstance( Effects.DIG_SLOWDOWN, duration, 1 ) ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "pale" ), - GET_TEXTURE_PATH( "pale_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/PoisonSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/PoisonSpiderEntity.java index a419bf6..220a1b5 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/PoisonSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/PoisonSpiderEntity.java @@ -13,7 +13,6 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,9 +28,10 @@ public class PoisonSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x0C424E ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x0C424E ).theme( BestiaryInfo.Theme.FOREST ) + .vanillaTextureWithEyes( "textures/entity/spider/cave_spider.png", "textures/entity/spider_eyes.png" ) + .addExperience( 1 ); } @SpecialMob.LanguageProvider @@ -49,13 +49,15 @@ public class PoisonSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PoisonSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PoisonSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public PoisonSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -67,13 +69,4 @@ public class PoisonSpiderEntity extends _SpecialSpiderEntity { livingTarget.addEffect( new EffectInstance( Effects.POISON, duration ) ); } } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/spider/cave_spider.png" ), - new ResourceLocation( "textures/entity/spider_eyes.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/WebSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/WebSpiderEntity.java index b9984aa..6142787 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/WebSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/WebSpiderEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.WebSpiderSpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -11,12 +12,10 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.monster.SpiderEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -33,19 +32,24 @@ public class WebSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xE7E7E7, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE7E7E7 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .spitAttackMultiplied( 0.1, 1.0, 2.0F, 1.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new WebSpiderSpeciesConfig( species, 0.02, 2, 6 ); } + /** @return This entity's species config. */ + @Override + public WebSpiderSpeciesConfig getConfig() { return (WebSpiderSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Weaver", @@ -61,18 +65,22 @@ public class WebSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WebSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public WebSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - webCount = 2 + random.nextInt( 5 ); - } - /** The number of cobwebs this spider can place. */ private int webCount; + public WebSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + webCount = getConfig().WEB.webCount.next( random ); + } + /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -113,13 +121,4 @@ public class WebSpiderEntity extends _SpecialSpiderEntity { if( saveTag.contains( References.TAG_AMMO, References.NBT_TYPE_NUMERICAL ) ) webCount = saveTag.getByte( References.TAG_AMMO ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "web" ), - GET_TEXTURE_PATH( "web_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/WitchSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/WitchSpiderEntity.java index 3a47f30..138aac6 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/WitchSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/WitchSpiderEntity.java @@ -4,18 +4,15 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.EffectType; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -31,16 +28,12 @@ public class WitchSpiderEntity extends _SpecialSpiderEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDD0E0E, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - forest - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialSpiderEntity.createAttributes() ) - .addAttribute( Attributes.ARMOR, 15.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDD0E0E ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .spitAttackMultiplied( 0.1, 1.0, 2.0F, 1.0 ) + .addToAttribute( Attributes.ARMOR, 15.0 ); } @SpecialMob.LanguageProvider @@ -58,13 +51,15 @@ public class WitchSpiderEntity extends _SpecialSpiderEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WitchSpiderEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public WitchSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public WitchSpiderEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -81,13 +76,4 @@ public class WitchSpiderEntity extends _SpecialSpiderEntity { // Witch spider is immune to debuffs return effect.getEffect().getCategory() != EffectType.HARMFUL && super.canBeAffected( effect ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "witch" ), - GET_TEXTURE_PATH( "witch_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java index 696096d..f323e66 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.spider; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpiderSpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.SpecialMobData; import fathertoast.specialmobs.common.util.References; @@ -21,13 +22,9 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.IServerWorld; import net.minecraft.world.World; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @@ -41,15 +38,26 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S public static MobFamily.Species<_SpecialSpiderEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xA80E0E ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA80E0E ) + .vanillaTextureWithEyes( "textures/entity/spider/spider.png", "textures/entity/spider_eyes.png" ) + .experience( 5 ).spider() + .spitAttack( 2.0, 1.0, 20, 40, 10.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return SpiderEntity.createAttributes(); + protected static final double DEFAULT_SPIT_CHANCE = 0.1; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SpiderSpeciesConfig( species, DEFAULT_SPIT_CHANCE ); } + /** @return This entity's species config. */ + public SpiderSpeciesConfig getConfig() { return (SpiderSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return SpiderEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Spider", @@ -67,21 +75,10 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S //--------------- Variant-Specific Breakouts ---------------- - public _SpecialSpiderEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); - - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedAttackSpread = 1.3F; - getSpecialData().rangedAttackCooldown = 40; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 10.0F; registerVariantGoals(); } @@ -110,20 +107,18 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S /** The parameter for special mob render scale. */ private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialSpiderEntity.class, DataSerializers.FLOAT ); + public _SpecialSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + if( !getConfig().SPIDERS.spitterChance.rollChance( random ) ) getSpecialData().disableRangedAttack(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); - } - - /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ - @Nullable - public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, - @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { - groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - // TODO ranged attack - return groupData; + specialData = new SpecialMobData<>( this, SCALE ); } @@ -133,7 +128,12 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S /** @return This mob's special data. */ @Override - public SpecialMobData<_SpecialSpiderEntity> getSpecialData() { return specialData; } + public final SpecialMobData<_SpecialSpiderEntity> getSpecialData() { return specialData; } + + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } /** @return The experience that should be dropped by this entity. */ @Override @@ -143,19 +143,6 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "spider/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/spider/spider.png" ), - new ResourceLocation( "textures/entity/spider_eyes.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/DominationWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/DominationWitchEntity.java index b10b9cc..2820fb7 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/DominationWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/DominationWitchEntity.java @@ -3,20 +3,17 @@ package fathertoast.specialmobs.common.entity.witch; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.potion.Potions; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -35,15 +32,11 @@ public class DominationWitchEntity extends _SpecialWitchEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFFF87E, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitchEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithEyes() + .addExperience( 2 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } @SpecialMob.LanguageProvider @@ -61,6 +54,11 @@ public class DominationWitchEntity extends _SpecialWitchEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return DominationWitchEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -70,10 +68,7 @@ public class DominationWitchEntity extends _SpecialWitchEntity { /** Ticks before this witch can use its pull ability. */ private int pullDelay; - public DominationWitchEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public DominationWitchEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to modify potion attacks. Return an empty item stack to cancel the potion throw. */ @Override @@ -110,13 +105,4 @@ public class DominationWitchEntity extends _SpecialWitchEntity { } super.aiStep(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "domination" ), - GET_TEXTURE_PATH( "domination_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/ShadowsWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/ShadowsWitchEntity.java index dc42e5a..b9f47d1 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/ShadowsWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/ShadowsWitchEntity.java @@ -14,7 +14,6 @@ import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -32,9 +31,10 @@ public class ShadowsWitchEntity extends _SpecialWitchEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000 ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureWithEyes() + .addExperience( 2 ).effectImmune( Effects.BLINDNESS, Effects.WITHER ); } @SpecialMob.LanguageProvider @@ -53,6 +53,11 @@ public class ShadowsWitchEntity extends _SpecialWitchEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return ShadowsWitchEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -61,11 +66,7 @@ public class ShadowsWitchEntity extends _SpecialWitchEntity { new EffectInstance( Effects.WITHER, 200, 0 ) ); - public ShadowsWitchEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().addPotionImmunity( Effects.BLINDNESS, Effects.WITHER ); - xpReward += 2; - } + public ShadowsWitchEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to modify potion attacks. Return an empty item stack to cancel the potion throw. */ @Override @@ -85,13 +86,4 @@ public class ShadowsWitchEntity extends _SpecialWitchEntity { } super.aiStep(); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "shadows" ), - GET_TEXTURE_PATH( "shadows_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/UndeadWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/UndeadWitchEntity.java index 30a999a..762cbbd 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/UndeadWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/UndeadWitchEntity.java @@ -3,6 +3,8 @@ package fathertoast.specialmobs.common.entity.witch; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.UndeadWitchSpeciesConfig; import fathertoast.specialmobs.common.entity.skeleton._SpecialSkeletonEntity; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; @@ -17,7 +19,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.potion.Potions; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -35,10 +36,20 @@ public class UndeadWitchEntity extends _SpecialWitchEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x799C65 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x799C65 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).undead(); } + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new UndeadWitchSpeciesConfig( species, 3, 6 ); + } + + /** @return This entity's species config. */ + public UndeadWitchSpeciesConfig getConfig() { return (UndeadWitchSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Lich", @@ -55,6 +66,11 @@ public class UndeadWitchEntity extends _SpecialWitchEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return UndeadWitchEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -63,9 +79,7 @@ public class UndeadWitchEntity extends _SpecialWitchEntity { public UndeadWitchEntity( EntityType entityType, World world ) { super( entityType, world ); - xpReward += 2; - - summons = 3 + random.nextInt( 4 ); + summons = getConfig().UNDEAD.summons.next( random ); } /** Override to modify potion attacks. Return an empty item stack to cancel the potion throw. */ @@ -127,12 +141,4 @@ public class UndeadWitchEntity extends _SpecialWitchEntity { if( saveTag.contains( References.TAG_SUMMONS, References.NBT_TYPE_NUMERICAL ) ) summons = saveTag.getByte( References.TAG_SUMMONS ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "undead" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/WildsWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/WildsWitchEntity.java index 087adcb..789a262 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/WildsWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/WildsWitchEntity.java @@ -3,15 +3,14 @@ package fathertoast.specialmobs.common.entity.witch; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.WildsWitchSpeciesConfig; import fathertoast.specialmobs.common.entity.spider.BabySpiderEntity; import fathertoast.specialmobs.common.entity.spider._SpecialSpiderEntity; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; -import net.minecraft.block.Blocks; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -21,7 +20,6 @@ import net.minecraft.potion.Potion; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; import net.minecraft.tags.FluidTags; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.IServerWorld; import net.minecraft.world.World; @@ -40,18 +38,22 @@ public class WildsWitchEntity extends _SpecialWitchEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xA80E0E ); - //TODO theme - forest + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA80E0E ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).spider() + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.7 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitchEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.7 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new WildsWitchSpeciesConfig( species, 1, 3, + 3, 6, 3, 4 ); } + /** @return This entity's species config. */ + public WildsWitchSpeciesConfig getConfig() { return (WildsWitchSpeciesConfig) getSpecies().config; } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Witch of the Wilds", @@ -67,6 +69,11 @@ public class WildsWitchEntity extends _SpecialWitchEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WildsWitchEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -79,13 +86,9 @@ public class WildsWitchEntity extends _SpecialWitchEntity { public WildsWitchEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().addStickyBlockImmunity( Blocks.COBWEB ); - getSpecialData().addPotionImmunity( Effects.POISON ); - xpReward += 1; - - spiderMounts = 1 + random.nextInt( 3 ); - spiderSwarms = 3 + random.nextInt( 4 ); - spiderSwarmSize = 3; + spiderMounts = getConfig().WILDS.mounts.next( random ); + spiderSwarms = getConfig().WILDS.swarms.next( random ); + spiderSwarmSize = getConfig().WILDS.swarmSize.next( random ); } /** Override to modify potion attacks. Return an empty item stack to cancel the potion throw. */ @@ -154,10 +157,10 @@ public class WildsWitchEntity extends _SpecialWitchEntity { mount.getHealth() < mount.getMaxHealth() ) { usePotion( makeSplashPotion( Potions.HEALING ) ); } - // else if( mount != null && random.nextFloat() < 0.5F && getTarget() != null && !mount.hasEffect( Effects.MOVEMENT_SPEED ) && - // getTarget().distanceToSqr( this ) > 121.0 ) { - // usePotion( makeSplashPotion( Potions.SWIFTNESS ) ); // TODO config - // } + else if( !MobFamily.WITCH.config.WITCHES.useSplashSwiftness.get() && mount != null && random.nextFloat() < 0.5F && getTarget() != null && + !mount.hasEffect( Effects.MOVEMENT_SPEED ) && getTarget().distanceToSqr( this ) > 121.0 ) { + usePotion( makeSplashPotion( Potions.SWIFTNESS ) ); + } else if( spiderMounts > 0 && random.nextFloat() < 0.15F && getVehicle() == null && getTarget() != null && getTarget().distanceToSqr( this ) > 100.0 ) { final _SpecialSpiderEntity spider = _SpecialSpiderEntity.SPECIES.entityType.get().create( level ); @@ -215,12 +218,4 @@ public class WildsWitchEntity extends _SpecialWitchEntity { if( saveTag.contains( References.TAG_EXTRA_BABIES, References.NBT_TYPE_NUMERICAL ) ) spiderSwarmSize = saveTag.getByte( References.TAG_EXTRA_BABIES ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "wilds" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/WindWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/WindWitchEntity.java index ff17bba..218db00 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/WindWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/WindWitchEntity.java @@ -6,7 +6,6 @@ import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.ai.AIHelper; import fathertoast.specialmobs.common.entity.ai.FluidPathNavigator; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -14,7 +13,6 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.fluid.Fluid; import net.minecraft.item.Items; @@ -24,7 +22,10 @@ import net.minecraft.pathfinding.PathNodeType; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.tags.FluidTags; -import net.minecraft.util.*; +import net.minecraft.util.DamageSource; +import net.minecraft.util.Direction; +import net.minecraft.util.IndirectEntityDamageSource; +import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -44,17 +45,12 @@ public class WindWitchEntity extends _SpecialWitchEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x6388B2 ); - //TODO theme - mountain - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitchEntity.createAttributes() ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x6388B2 ).theme( BestiaryInfo.Theme.MOUNTAIN ) + .uniqueTextureWithEyes() + .addExperience( 2 ).fallImmune() + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } @SpecialMob.LanguageProvider @@ -73,6 +69,11 @@ public class WindWitchEntity extends _SpecialWitchEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return WindWitchEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- @@ -81,9 +82,6 @@ public class WindWitchEntity extends _SpecialWitchEntity { public WindWitchEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setFallDamageMultiplier( 0.0F ); - xpReward += 2; - setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() ); } @@ -245,13 +243,4 @@ public class WindWitchEntity extends _SpecialWitchEntity { public void readVariantSaveData( CompoundNBT saveTag ) { setPathfindingMalus( PathNodeType.WATER, PathNodeType.WALKABLE.getMalus() ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "wind" ), - GET_TEXTURE_PATH( "wind_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witch/_SpecialWitchEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witch/_SpecialWitchEntity.java index a4354e2..d30bc40 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witch/_SpecialWitchEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witch/_SpecialWitchEntity.java @@ -31,7 +31,6 @@ import net.minecraft.potion.*; import net.minecraft.tags.FluidTags; import net.minecraft.util.DamageSource; import net.minecraft.util.IItemProvider; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -53,14 +52,14 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe public static MobFamily.Species<_SpecialWitchEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xA80E0E ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xA80E0E ) + .vanillaTextureBaseOnly( "textures/entity/witch.png" ) + .experience( 5 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return WitchEntity.createAttributes(); - } + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return WitchEntity.createAttributes(); } @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { @@ -79,16 +78,11 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe //--------------- Variant-Specific Breakouts ---------------- - public _SpecialWitchEntity( EntityType entityType, World world ) { - super( entityType, world ); - usingTime = Integer.MAX_VALUE; // Effectively disable vanilla witch potion drinking logic in combo with "fake drinking" - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); + //TODO reapply vanilla attack AI to use SMD ranged attack stats registerVariantGoals(); } @@ -195,8 +189,8 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe } else if( random.nextFloat() < 0.5F && getTarget() != null && !hasEffect( Effects.MOVEMENT_SPEED ) && getTarget().distanceToSqr( this ) > 121.0 ) { - //usePotion( ____ ? makeSplashPotion( Potions.SWIFTNESS ) : makePotion( Potions.SWIFTNESS ) ); - usePotion( makeSplashPotion( Potions.SWIFTNESS ) ); // TODO config + usePotion( MobFamily.WITCH.config.WITCHES.useSplashSwiftness.get() ? makeSplashPotion( Potions.SWIFTNESS ) : + makePotion( Potions.SWIFTNESS ) ); } else { tryVariantUsingPotion(); @@ -233,11 +227,17 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe /** While the witch is drinking a potion, it stores its 'actual' held item here. */ public ItemStack sheathedItem = ItemStack.EMPTY; + public _SpecialWitchEntity( EntityType entityType, World world ) { + super( entityType, world ); + usingTime = Integer.MAX_VALUE; // Effectively disable vanilla witch potion drinking logic in combo with "fake drinking" + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Called each AI tick to update potion-drinking behavior. */ @@ -356,6 +356,11 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe @Override public SpecialMobData<_SpecialWitchEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -364,18 +369,6 @@ public class _SpecialWitchEntity extends WitchEntity implements ISpecialMob<_Spe @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "witch/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/witch.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/BruteWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/BruteWitherSkeletonEntity.java index 952d998..a01b8eb 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/BruteWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/BruteWitherSkeletonEntity.java @@ -4,14 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; @@ -19,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -35,17 +32,12 @@ public class BruteWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.85F, 2.9F ); - return new BestiaryInfo( 0xFFF87E ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ) + .uniqueTextureWithOverlay() + .size( 1.44F, 0.85F, 2.9F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ); } @SpecialMob.LanguageProvider @@ -64,14 +56,15 @@ public class BruteWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BruteWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BruteWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.44F ); - xpReward += 2; - } + public BruteWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -89,14 +82,4 @@ public class BruteWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "brute" ), - null, - GET_TEXTURE_PATH( "brute_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GatlingWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GatlingWitherSkeletonEntity.java index 81c0039..17306ac 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GatlingWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GatlingWitherSkeletonEntity.java @@ -3,16 +3,14 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,16 +26,18 @@ public class GatlingWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFFFF0B ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFFF0B ) + .uniqueOverlayTexture() + .addExperience( 2 ) + .multiplyRangedSpread( 2.0 ).multiplyRangedWalkSpeed( 0.3 ).rangedCooldown( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0F, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -56,32 +56,13 @@ public class GatlingWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GatlingWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public GatlingWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - setRangedAI( 0.3, 1 ); - getSpecialData().rangedAttackSpread *= 2.0F; - } - - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 1.0; } - - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/skeleton/wither_skeleton.png" ), - null, - GET_TEXTURE_PATH( "gatling_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public GatlingWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GiantWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GiantWitherSkeletonEntity.java index fc10ec0..b039d94 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GiantWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/GiantWitherSkeletonEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,17 +24,12 @@ public class GiantWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.95F, 3.6F ); - return new BestiaryInfo( 0x474D4D ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x474D4D ) + .size( 1.8F, 0.95F, 3.6F ) + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 2.0 ); } @SpecialMob.LanguageProvider @@ -55,20 +47,17 @@ public class GiantWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GiantWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public GiantWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.8F ); maxUpStep = 1.0F; - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; } /** Sets this entity as a baby. */ diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/KnightWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/KnightWitherSkeletonEntity.java index e7a5c7a..336d355 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/KnightWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/KnightWitherSkeletonEntity.java @@ -3,13 +3,12 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -30,18 +29,17 @@ public class KnightWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDDDDDD ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDDDDDD ) + .addExperience( 2 ).multiplyRangedSpread( 1.2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 4.0 ).addToRangedDamage( 4.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 4.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 0.05, 1.0 ); } @SpecialMob.LanguageProvider @@ -59,36 +57,27 @@ public class KnightWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return KnightWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public KnightWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 4.0F; - getSpecialData().rangedAttackSpread *= 1.2F; - } + public KnightWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < 0.95 ) { + + if( getItemBySlot( EquipmentSlotType.MAINHAND ).getItem() == Items.STONE_SWORD ) { setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.IRON_SWORD ) ); - setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); } setItemSlot( EquipmentSlotType.HEAD, new ItemStack( Items.CHAINMAIL_HELMET ) ); setItemSlot( EquipmentSlotType.CHEST, new ItemStack( Items.CHAINMAIL_CHESTPLATE ) ); setItemSlot( EquipmentSlotType.LEGS, new ItemStack( Items.CHAINMAIL_LEGGINGS ) ); setItemSlot( EquipmentSlotType.FEET, new ItemStack( Items.CHAINMAIL_BOOTS ) ); } - - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 1.0; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/NinjaWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/NinjaWitherSkeletonEntity.java index 2824176..d7cdbf9 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/NinjaWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/NinjaWitherSkeletonEntity.java @@ -3,10 +3,11 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.ai.INinja; import fathertoast.specialmobs.common.entity.ai.goal.NinjaGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -15,7 +16,6 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.datasync.DataParameter; @@ -23,7 +23,10 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.*; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.DamageSource; +import net.minecraft.util.Hand; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.DifficultyInstance; @@ -44,15 +47,17 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x333366 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x333366 ) + .uniqueOverlayTexture() + .addExperience( 2 ).pressurePlateImmune() + .multiplyRangedCooldown( 0.5F ).rangedMaxRange( 9.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.2 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.2 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 0.5, 0.0 ); } @SpecialMob.LanguageProvider @@ -71,18 +76,19 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return NinjaWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public NinjaWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public NinjaWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - setRangedAI( 1.0, 10, 9.0F ); goalSelector.addGoal( -9, new NinjaGoal<>( this ) ); } @@ -93,10 +99,6 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl setCanPickUpLoot( true ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.5; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { revealTo( target, true ); } @@ -193,16 +195,6 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl } } - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/skeleton/wither_skeleton.png" ), - null, - GET_TEXTURE_PATH( "ninja_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- INinja Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SniperWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SniperWitherSkeletonEntity.java index ac79144..a6ae9f4 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SniperWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SniperWitherSkeletonEntity.java @@ -3,16 +3,14 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,16 +26,18 @@ public class SniperWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x486720 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x486720 ) + .uniqueTextureWithOverlay() + .addExperience( 1 ) + .multiplyRangedSpread( 0.05 ).multiplyRangedWalkSpeed( 0.3 ).multiplyRangedCooldown( 1.5F ).rangedMaxRange( 25.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 4.0 ) + .addToAttribute( Attributes.FOLLOW_RANGE, 16.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.FOLLOW_RANGE, 16.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -56,33 +56,13 @@ public class SniperWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SniperWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public SniperWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - setRangedAI( 0.3, 30, 25.0F ); - getSpecialData().rangedAttackDamage += 2.0F; - getSpecialData().rangedAttackSpread *= 0.05F; - } - - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 1.0; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "sniper" ), - null, - GET_TEXTURE_PATH( "sniper_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } + public SniperWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SpitfireWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SpitfireWitherSkeletonEntity.java index 9402f8a..170ac49 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SpitfireWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/SpitfireWitherSkeletonEntity.java @@ -3,18 +3,17 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.SmallFireballEntity; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -31,17 +30,18 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.95F, 3.6F ); - return new BestiaryInfo( 0xDC1A00, BestiaryInfo.BaseWeight.LOW ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDC1A00 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureWithEyes() + .size( 1.8F, 0.95F, 3.6F ) + .addExperience( 2 ).waterSensitive().rangedDamage( 0.0 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialWitherSkeletonEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, 1.0F, DEFAULT_SHIELD_CHANCE ); } @SpecialMob.LanguageProvider @@ -59,27 +59,19 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return SpitfireWitherSkeletonEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public SpitfireWitherSkeletonEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.8F ); - getSpecialData().setDamagedByWater( true ); maxUpStep = 1.0F; - xpReward += 2; } - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; - } - - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 1.0; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -91,7 +83,7 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { public void performRangedAttack( LivingEntity target, float damageMulti ) { if( !isSilent() ) level.levelEvent( null, References.EVENT_BLAZE_SHOOT, blockPosition(), 0 ); - final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().rangedAttackSpread; + final float accelVariance = MathHelper.sqrt( distanceTo( target ) ) * 0.5F * getSpecialData().getRangedAttackSpread(); for( int i = 0; i < 4; i++ ) { final double dX = target.getX() - getX() + getRandom().nextGaussian() * accelVariance; @@ -111,13 +103,4 @@ public class SpitfireWitherSkeletonEntity extends _SpecialWitherSkeletonEntity { /** @return True if this entity is a baby. */ @Override public boolean isBaby() { return false; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fire" ), - GET_TEXTURE_PATH( "fire_eyes" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/_SpecialWitherSkeletonEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/_SpecialWitherSkeletonEntity.java index 8a52987..93863ab 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/_SpecialWitherSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/witherskeleton/_SpecialWitherSkeletonEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.witherskeleton; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SkeletonSpeciesConfig; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.SpecialMobData; @@ -12,7 +13,6 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.*; -import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; @@ -34,7 +34,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -44,7 +43,6 @@ import net.minecraft.world.World; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.UUID; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -57,15 +55,28 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement public static MobFamily.Species<_SpecialWitherSkeletonEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x474D4D ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x474D4D ) + .vanillaTextureBaseOnly( "textures/entity/skeleton/wither_skeleton.png" ) + .familySize( 1.2F ) + .experience( 5 ).undead().fireImmune() + .bowAttack( 2.0, 1.0, 1.0, 20, 15.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return WitherSkeletonEntity.createAttributes(); + protected static final double DEFAULT_BOW_CHANCE = 0.05; + protected static final double DEFAULT_SHIELD_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new SkeletonSpeciesConfig( species, DEFAULT_BOW_CHANCE, DEFAULT_SHIELD_CHANCE ); } + /** @return This entity's species config. */ + public SkeletonSpeciesConfig getConfig() { return (SkeletonSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return WitherSkeletonEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Wither Skeleton", @@ -83,57 +94,19 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement //--------------- Variant-Specific Breakouts ---------------- - public _SpecialWitherSkeletonEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { super.registerGoals(); - - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedAttackCooldown = 20; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 15.0F; registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { setRangedAI( 1.0, 20, 0.0F ); } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime ) { - getSpecialData().rangedWalkSpeed = (float) walkSpeed; - getSpecialData().rangedAttackCooldown = cooldownTime; - getSpecialData().rangedAttackMaxCooldown = cooldownTime; - } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime, float range ) { - setRangedAI( walkSpeed, cooldownTime ); - getSpecialData().rangedAttackMaxRange = range; - } - /** Override to change this entity's attack goal priority. */ protected int getVariantAttackPriority() { return 4; } - /** Called during spawn finalization to set starting equipment. */ - @Override - protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { - super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < getVariantBowChance() ) { //TODO config the default 5% chance - setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.BOW ) ); - } - } - - /** Override to change this entity's chance to spawn with a bow. */ - protected double getVariantBowChance() { return getSpecialData().rangedAttackMaxRange > 0.0F ? 0.05 : 0.0; } - /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { @@ -148,7 +121,7 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement final double dZ = target.getZ() - getZ(); final double dH = MathHelper.sqrt( dX * dX + dZ * dZ ); arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F, - getSpecialData().rangedAttackSpread * (14 - 4 * level.getDifficulty().getId()) ); + getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) ); playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) ); level.addFreshEntity( arrow ); @@ -157,7 +130,7 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement /** @return The arrow for this skeleton to shoot. */ @Override protected AbstractArrowEntity getArrow( ItemStack arrowItem, float damageMulti ) { - return getVariantArrow( super.getArrow( arrowItem, damageMulti * getSpecialData().rangedAttackDamage ), + return getVariantArrow( super.getArrow( arrowItem, damageMulti * getSpecialData().getRangedAttackDamage() ), arrowItem, damageMulti ); } @@ -191,11 +164,16 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement /** This entity's attack AI. */ private Goal currentAttackAI; + public _SpecialWitherSkeletonEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.2F ); + specialData = new SpecialMobData<>( this, SCALE ); entityData.define( IS_BABY, false ); } @@ -204,10 +182,25 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); - setBaby( random.nextDouble() < 0.05 ); //TODO config + + setBaby( MobFamily.WITHER_SKELETON.config.SKELETONS.babyChance.rollChance( random ) ); + return groupData; } + /** Called during spawn finalization to set starting equipment. */ + @Override + protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { + super.populateDefaultEquipmentSlots( difficulty ); + + if( getSpecialData().getRangedAttackMaxRange() > 0.0F && getConfig().SKELETONS.bowEquipChance.rollChance( random ) ) { + setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.BOW ) ); + } + else if( getConfig().SKELETONS.shieldEquipChance.rollChance( random ) ) { + setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); + } + } + /** Called to set this entity's attack AI based on current equipment. */ @Override public void reassessWeaponGoal() { @@ -217,9 +210,9 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement final SpecialMobData<_SpecialWitherSkeletonEntity> data = getSpecialData(); final ItemStack weapon = getItemInHand( ProjectileHelper.getWeaponHoldingHand( this, item -> item instanceof BowItem ) ); - if( data.rangedAttackMaxRange > 0.0F && weapon.getItem() == Items.BOW ) { - currentAttackAI = new RangedBowAttackGoal<>( this, data.rangedWalkSpeed, - data.rangedAttackCooldown, data.rangedAttackMaxRange ); + if( data.getRangedAttackMaxRange() > 0.0F && weapon.getItem() == Items.BOW ) { + currentAttackAI = new RangedBowAttackGoal<>( this, data.getRangedWalkSpeed(), + data.getRangedAttackCooldown(), data.getRangedAttackMaxRange() ); } else { currentAttackAI = new MeleeAttackGoal( this, 1.2, false ); @@ -233,9 +226,6 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement /** The parameter for baby status. */ private static final DataParameter IS_BABY = EntityDataManager.defineId( _SpecialWitherSkeletonEntity.class, DataSerializers.BOOLEAN ); - /** The speed boost to apply when in baby state. */ - private static final AttributeModifier BABY_SPEED_BOOST = new AttributeModifier( UUID.fromString( "B9766B59-9566-4402-BC1F-2EE2A276D836" ), - "Baby speed boost", 0.5, AttributeModifier.Operation.MULTIPLY_BASE ); /** Sets this entity as a baby. */ @Override @@ -244,9 +234,9 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement if( level != null && !level.isClientSide ) { final ModifiableAttributeInstance attributeInstance = getAttribute( Attributes.MOVEMENT_SPEED ); //noinspection ConstantConditions - attributeInstance.removeModifier( BABY_SPEED_BOOST ); + attributeInstance.removeModifier( References.BABY_SPEED_BOOST ); if( value ) { - attributeInstance.addTransientModifier( BABY_SPEED_BOOST ); + attributeInstance.addTransientModifier( References.BABY_SPEED_BOOST ); } } } @@ -286,6 +276,11 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement @Override public SpecialMobData<_SpecialWitherSkeletonEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -294,16 +289,6 @@ public class _SpecialWitherSkeletonEntity extends WitherSkeletonEntity implement @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "witherskeleton/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/skeleton/wither_skeleton.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/BruteZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/BruteZombieEntity.java index 617b6fe..1d5a2f4 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/BruteZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/BruteZombieEntity.java @@ -4,14 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; @@ -19,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -35,17 +32,12 @@ public class BruteZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.7F, 2.35F ); - return new BestiaryInfo( 0xFFF87E ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ) + .uniqueTextureWithOverlay() + .size( 1.2F, 0.7F, 2.35F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ); } @SpecialMob.LanguageProvider @@ -64,14 +56,15 @@ public class BruteZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BruteZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BruteZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - xpReward += 2; - } + public BruteZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -89,14 +82,4 @@ public class BruteZombieEntity extends _SpecialZombieEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "brute" ), - null, - GET_TEXTURE_PATH( "brute_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/FireZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/FireZombieEntity.java index 33e6060..674584c 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/FireZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/FireZombieEntity.java @@ -8,12 +8,10 @@ import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; @@ -31,10 +29,10 @@ public class FireZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.fireImmune(); - return new BestiaryInfo( 0xDC1A00 ); - //TODO theme - fire + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDC1A00 ).theme( BestiaryInfo.Theme.FIRE ) + .uniqueTextureBaseOnly() + .addExperience( 1 ).fireImmune().waterSensitive(); } @SpecialMob.LanguageProvider @@ -53,14 +51,15 @@ public class FireZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FireZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FireZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setDamagedByWater( true ); - xpReward += 1; - } + public FireZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -94,12 +93,4 @@ public class FireZombieEntity extends _SpecialZombieEntity { /** @return The sound this entity makes while walking. */ @Override protected SoundEvent getStepSound() { return SoundEvents.HUSK_STEP; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "fire" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/FishingZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/FishingZombieEntity.java index 0093e27..37f2388 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/FishingZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/FishingZombieEntity.java @@ -3,8 +3,10 @@ package fathertoast.specialmobs.common.entity.zombie; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig; import fathertoast.specialmobs.common.entity.ai.IAngler; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder; import fathertoast.specialmobs.datagen.loot.LootHelper; @@ -12,8 +14,6 @@ import fathertoast.specialmobs.datagen.loot.LootPoolBuilder; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.FishingRodItem; @@ -39,16 +39,16 @@ public class FishingZombieEntity extends _SpecialZombieEntity implements IAngler public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x2D41F4 ); - //TODO theme - fishing + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x2D41F4 ).theme( BestiaryInfo.Theme.FISHING ) + .addExperience( 2 ).drownImmune().fluidPushImmune() + .bowAttack( 0.0, 1.0, 1.0, 40, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new ZombieSpeciesConfig( species, 0.0, 0.0 ); } @SpecialMob.LanguageProvider @@ -71,24 +71,19 @@ public class FishingZombieEntity extends _SpecialZombieEntity implements IAngler @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FishingZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FishingZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setCanBreatheInWater( true ); - getSpecialData().setIgnoreWaterPush( true ); - xpReward += 2; - } + public FishingZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 0.7F; - getSpecialData().rangedAttackCooldown = 32; - getSpecialData().rangedAttackMaxCooldown = 48; - getSpecialData().rangedAttackMaxRange = 10.0F; - //TODO add angler AI @ attack priority } @@ -106,10 +101,6 @@ public class FishingZombieEntity extends _SpecialZombieEntity implements IAngler setCanPickUpLoot( false ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.0; } - //--------------- IAngler Implementations ---------------- @@ -135,7 +126,7 @@ public class FishingZombieEntity extends _SpecialZombieEntity implements IAngler @Override public ItemStack getItemBySlot( EquipmentSlotType slot ) { // Display a stick in place of the "cast fishing rod" when the fancy render is disabled - if( level.isClientSide() && /*!Config.get().GENERAL.FANCY_FISHING_MOBS &&*/ EquipmentSlotType.MAINHAND.equals( slot ) ) { + if( level.isClientSide() && !Config.MAIN.GENERAL.fancyFishingMobs.get() && EquipmentSlotType.MAINHAND.equals( slot ) ) { final ItemStack held = super.getItemBySlot( slot ); if( !held.isEmpty() && held.getItem() instanceof FishingRodItem && isLineOut() ) { return new ItemStack( Items.STICK ); diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/GiantZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/GiantZombieEntity.java index 2320fd3..076fad1 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/GiantZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/GiantZombieEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.zombie; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,17 +24,12 @@ public class GiantZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.95F ); - return new BestiaryInfo( 0x799C65 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x799C65 ) + .size( 1.5F, 0.9F, 2.95F ) + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 2.0 ); } @SpecialMob.LanguageProvider @@ -55,20 +47,17 @@ public class GiantZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GiantZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public GiantZombieEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); maxUpStep = 1.0F; - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; } /** Sets this entity as a baby. */ diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/HungryZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/HungryZombieEntity.java index ed286c0..a89874f 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/HungryZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/HungryZombieEntity.java @@ -4,20 +4,17 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Food; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; @@ -36,16 +33,12 @@ public class HungryZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xAB1518 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xAB1518 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).regen( 30 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -64,20 +57,15 @@ public class HungryZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HungryZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public HungryZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setRegenerationTime( 30 ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - disableRangedAI(); - } + public HungryZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override @@ -86,10 +74,6 @@ public class HungryZombieEntity extends _SpecialZombieEntity { setCanPickUpLoot( false ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.0; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -109,12 +93,4 @@ public class HungryZombieEntity extends _SpecialZombieEntity { MobHelper.stealLife( this, (LivingEntity) target, 2.0F ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "hungry" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/HuskZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/HuskZombieEntity.java index 49f8179..d75e41f 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/HuskZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/HuskZombieEntity.java @@ -18,7 +18,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.world.World; @@ -36,15 +35,15 @@ public class HuskZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xE6CC94, BestiaryInfo.BaseWeight.LOW ); - //TODO theme - desert + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xE6CC94 ).weight( BestiaryInfo.DefaultWeight.LOW ).theme( BestiaryInfo.Theme.DESERT ) + .vanillaTextureBaseOnly( "textures/entity/zombie/husk.png" ) + .size( 1.0625F, 0.6F, 1.95F ) + .addExperience( 1 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return HuskEntity.createAttributes(); - } + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return HuskEntity.createAttributes(); } @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { @@ -60,14 +59,15 @@ public class HuskZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HuskZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public HuskZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.0625F ); - xpReward += 1; - } + public HuskZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -91,14 +91,6 @@ public class HuskZombieEntity extends _SpecialZombieEntity { return arrow; } - private static final ResourceLocation[] TEXTURES = { - new ResourceLocation( "textures/entity/zombie/husk.png" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- Husk Implementations ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/MadScientistZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/MadScientistZombieEntity.java index d07045e..c5ed8d0 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/MadScientistZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/MadScientistZombieEntity.java @@ -7,20 +7,17 @@ import fathertoast.specialmobs.common.core.register.SMItems; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.ai.AIHelper; import fathertoast.specialmobs.common.entity.ai.goal.ChargeCreeperGoal; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; @@ -37,15 +34,10 @@ public class MadScientistZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xDED4C6 ); // TODO - Temp color - //TODO theme - madness - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xDED4C6 ) + .uniqueTextureWithOverlay() + .addExperience( 2 ).disableRangedAttack(); } @SpecialMob.LanguageProvider @@ -63,21 +55,21 @@ public class MadScientistZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return MadScientistZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public MadScientistZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } + public MadScientistZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - disableRangedAI(); - AIHelper.insertGoal( goalSelector, 2, new ChargeCreeperGoal<>( - this, getAttributeValue( Attributes.MOVEMENT_SPEED ) * 1.25D, 20.0D, + this, getAttributeValue( Attributes.MOVEMENT_SPEED ) * 1.25, 20.0, ( madman, creeper ) -> creeper.isAlive() && !creeper.isPowered() && madman.getSensing().canSee( creeper ) ) ); } @@ -94,10 +86,6 @@ public class MadScientistZombieEntity extends _SpecialZombieEntity { setDropChance( EquipmentSlotType.MAINHAND, 0.0F ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.0; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -108,14 +96,4 @@ public class MadScientistZombieEntity extends _SpecialZombieEntity { livingTarget.addEffect( new EffectInstance( Effects.POISON, duration, 1 ) ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "madscientist" ), - null, - GET_TEXTURE_PATH( "madscientist_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/PlagueZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/PlagueZombieEntity.java index d295b4c..f29a21f 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/PlagueZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/PlagueZombieEntity.java @@ -4,7 +4,6 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -12,13 +11,11 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -34,16 +31,11 @@ public class PlagueZombieEntity extends _SpecialZombieEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x8AA838 ); - //TODO theme - forest - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombieEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.1 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x8AA838 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.1 ); } @SpecialMob.LanguageProvider @@ -62,13 +54,15 @@ public class PlagueZombieEntity extends _SpecialZombieEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PlagueZombieEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PlagueZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public PlagueZombieEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -86,12 +80,4 @@ public class PlagueZombieEntity extends _SpecialZombieEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "plague" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombie/_SpecialZombieEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombie/_SpecialZombieEntity.java index dde2b9d..12f649d 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombie/_SpecialZombieEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombie/_SpecialZombieEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.zombie; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.SpecialMobData; @@ -34,7 +35,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -56,15 +56,27 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM public static MobFamily.Species<_SpecialZombieEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x799C65 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x799C65 ) + .vanillaTextureBaseOnly( "textures/entity/zombie/zombie.png" ) + .experience( 5 ).undead() + .bowAttack( 2.0, 1.4, 0.8, 30, 12.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return ZombieEntity.createAttributes(); + protected static final double DEFAULT_BOW_CHANCE = 0.05; + protected static final double DEFAULT_SHIELD_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new ZombieSpeciesConfig( species, DEFAULT_BOW_CHANCE, DEFAULT_SHIELD_CHANCE ); } + /** @return This entity's species config. */ + public ZombieSpeciesConfig getConfig() { return (ZombieSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return ZombieEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Zombie", @@ -82,12 +94,6 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM //--------------- Variant-Specific Breakouts ---------------- - public _SpecialZombieEntity( EntityType entityType, World world ) { - super( entityType, world ); - reassessWeaponGoal(); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -96,34 +102,12 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM AIHelper.replaceHurtByTarget( this, new SpecialHurtByTargetGoal( this, ZombieEntity.class ) .setAlertOthers( ZombifiedPiglinEntity.class ) ); - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedAttackSpread = 1.4F; - getSpecialData().rangedWalkSpeed = 0.8F; - getSpecialData().rangedAttackCooldown = 30; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 12.0F; registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { setRangedAI( 1.0, 20, 0.0F ); } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime ) { - getSpecialData().rangedWalkSpeed = (float) walkSpeed; - getSpecialData().rangedAttackCooldown = cooldownTime; - getSpecialData().rangedAttackMaxCooldown = cooldownTime; - } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime, float range ) { - setRangedAI( walkSpeed, cooldownTime ); - getSpecialData().rangedAttackMaxRange = range; - } - /** Override to change this entity's attack goal priority. */ protected int getVariantAttackPriority() { return 2; } @@ -131,14 +115,15 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM @Override protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < getVariantBowChance() ) { //TODO config the default 5% chance + + if( getSpecialData().getRangedAttackMaxRange() > 0.0F && getConfig().ZOMBIES.bowEquipChance.rollChance( random ) ) { setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.BOW ) ); } + else if( getConfig().ZOMBIES.shieldEquipChance.rollChance( random ) ) { + setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); + } } - /** Override to change this entity's chance to spawn with a bow. */ - protected double getVariantBowChance() { return getSpecialData().rangedAttackMaxRange > 0.0F ? 0.05 : 0.0; } - /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { @@ -153,7 +138,7 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM final double dZ = target.getZ() - getZ(); final double dH = MathHelper.sqrt( dX * dX + dZ * dZ ); arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F, - getSpecialData().rangedAttackSpread * (14 - 4 * level.getDifficulty().getId()) ); + getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) ); playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) ); level.addFreshEntity( arrow ); @@ -162,7 +147,7 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM /** @return The arrow for this zombie to shoot. */ protected AbstractArrowEntity getArrow( ItemStack arrowItem, float damageMulti ) { return getVariantArrow( ProjectileHelper.getMobArrow( this, arrowItem, - damageMulti * getSpecialData().rangedAttackDamage ), arrowItem, damageMulti ); + damageMulti * getSpecialData().getRangedAttackDamage() ), arrowItem, damageMulti ); } /** Override to modify this entity's ranged attack projectile. */ @@ -195,11 +180,18 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM /** This entity's attack AI. */ private Goal currentAttackAI; + public _SpecialZombieEntity( EntityType entityType, World world ) { + super( entityType, world ); + reassessWeaponGoal(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ @@ -207,7 +199,9 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); + reassessWeaponGoal(); + return groupData; } @@ -226,9 +220,9 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM final SpecialMobData<_SpecialZombieEntity> data = getSpecialData(); final ItemStack weapon = getItemInHand( ProjectileHelper.getWeaponHoldingHand( this, item -> item instanceof BowItem ) ); - if( data.rangedAttackMaxRange > 0.0F && weapon.getItem() == Items.BOW ) { - currentAttackAI = new RangedBowAttackGoal<>( this, data.rangedWalkSpeed, - data.rangedAttackCooldown, data.rangedAttackMaxRange ); + if( data.getRangedAttackMaxRange() > 0.0F && weapon.getItem() == Items.BOW ) { + currentAttackAI = new RangedBowAttackGoal<>( this, data.getRangedWalkSpeed(), + data.getRangedAttackCooldown(), data.getRangedAttackMaxRange() ); } else { currentAttackAI = new ZombieAttackGoal( this, 1.0, false ); @@ -246,6 +240,11 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM @Override public SpecialMobData<_SpecialZombieEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -254,16 +253,6 @@ public class _SpecialZombieEntity extends ZombieEntity implements IRangedAttackM @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "zombie/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/zombie/zombie.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/BruteZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/BruteZombifiedPiglinEntity.java index 73d90b7..a4aba32 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/BruteZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/BruteZombifiedPiglinEntity.java @@ -4,14 +4,12 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; @@ -20,7 +18,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; @@ -37,17 +34,12 @@ public class BruteZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.7F, 2.35F ); - return new BestiaryInfo( 0xFFF87E ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFFF87E ) + .uniqueTextureWithOverlay() + .size( 1.2F, 0.7F, 2.35F ) + .addExperience( 2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ); } @SpecialMob.LanguageProvider @@ -66,14 +58,15 @@ public class BruteZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return BruteZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public BruteZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setBaseScale( 1.2F ); - xpReward += 2; - } + public BruteZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override @@ -101,14 +94,4 @@ public class BruteZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "brute" ), - null, - GET_TEXTURE_PATH( "brute_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/FishingZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/FishingZombifiedPiglinEntity.java index 3f57f28..621be9e 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/FishingZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/FishingZombifiedPiglinEntity.java @@ -3,8 +3,10 @@ package fathertoast.specialmobs.common.entity.zombifiedpiglin; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig; import fathertoast.specialmobs.common.entity.ai.IAngler; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootEntryItemBuilder; import fathertoast.specialmobs.datagen.loot.LootHelper; @@ -12,8 +14,6 @@ import fathertoast.specialmobs.datagen.loot.LootPoolBuilder; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.FishingRodItem; @@ -39,16 +39,16 @@ public class FishingZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x2D41F4 ); - //TODO theme - fishing + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x2D41F4 ).theme( BestiaryInfo.Theme.FISHING ) + .addExperience( 2 ).drownImmune().fluidPushImmune() + .bowAttack( 0.0, 1.0, 1.0, 40, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new ZombieSpeciesConfig( species, 0.0, 0.0 ); } @SpecialMob.LanguageProvider @@ -71,24 +71,19 @@ public class FishingZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return FishingZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public FishingZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setCanBreatheInWater( true ); - getSpecialData().setIgnoreWaterPush( true ); - xpReward += 2; - } + public FishingZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to change this entity's AI goals. */ @Override protected void registerVariantGoals() { - getSpecialData().rangedAttackSpread *= 0.7F; - getSpecialData().rangedAttackCooldown = 32; - getSpecialData().rangedAttackMaxCooldown = 48; - getSpecialData().rangedAttackMaxRange = 10.0F; - //TODO add angler AI @ attack priority } @@ -106,14 +101,6 @@ public class FishingZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity setCanPickUpLoot( false ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.0; } - - /** Override to change this entity's chance to spawn with a shield. */ - @Override - protected double getVariantShieldChance() { return 0.0; } - //--------------- IAngler Implementations ---------------- @@ -139,7 +126,7 @@ public class FishingZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity @Override public ItemStack getItemBySlot( EquipmentSlotType slot ) { // Display a stick in place of the "cast fishing rod" when the fancy render is disabled - if( level.isClientSide() && /*!Config.get().GENERAL.FANCY_FISHING_MOBS &&*/ EquipmentSlotType.MAINHAND.equals( slot ) ) { + if( level.isClientSide() && !Config.MAIN.GENERAL.fancyFishingMobs.get() && EquipmentSlotType.MAINHAND.equals( slot ) ) { final ItemStack held = super.getItemBySlot( slot ); if( !held.isEmpty() && held.getItem() instanceof FishingRodItem && isLineOut() ) { return new ItemStack( Items.STICK ); diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/GiantZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/GiantZombifiedPiglinEntity.java index 574b330..9f031e4 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/GiantZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/GiantZombifiedPiglinEntity.java @@ -3,13 +3,10 @@ package fathertoast.specialmobs.common.entity.zombifiedpiglin; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.item.Items; import net.minecraft.world.World; @@ -27,17 +24,12 @@ public class GiantZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - entityType.sized( 0.9F, 2.95F ); - return new BestiaryInfo( 0x4C7129 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 20.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 2.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x4C7129 ) + .size( 1.5F, 0.9F, 2.95F ) + .addExperience( 1 ) + .addToAttribute( Attributes.MAX_HEALTH, 20.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 2.0 ).addToRangedDamage( 2.0 ); } @SpecialMob.LanguageProvider @@ -55,20 +47,17 @@ public class GiantZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return GiantZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- public GiantZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); - getSpecialData().setBaseScale( 1.5F ); maxUpStep = 1.0F; - xpReward += 1; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 2.0F; } /** Sets this entity as a baby. */ diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/HungryZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/HungryZombifiedPiglinEntity.java index caecfe3..ce24c49 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/HungryZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/HungryZombifiedPiglinEntity.java @@ -4,20 +4,17 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Food; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; @@ -36,16 +33,12 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xAB1518 ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.3 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xAB1518 ) + .uniqueTextureBaseOnly() + .addExperience( 2 ).regen( 30 ).disableRangedAttack() + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.3 ); } @SpecialMob.LanguageProvider @@ -64,20 +57,15 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return HungryZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public HungryZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - getSpecialData().setRegenerationTime( 30 ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - disableRangedAI(); - } + public HungryZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override @@ -86,10 +74,6 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { setCanPickUpLoot( false ); } - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.0; } - /** Override to apply effects when this entity hits a target with a melee attack. */ @Override protected void onVariantAttack( Entity target ) { @@ -109,12 +93,4 @@ public class HungryZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { MobHelper.stealLife( this, (LivingEntity) target, 2.0F ); } } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "hungry" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/KnightZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/KnightZombifiedPiglinEntity.java index 95b9386..4c5acfc 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/KnightZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/KnightZombifiedPiglinEntity.java @@ -3,13 +3,12 @@ package fathertoast.specialmobs.common.entity.zombifiedpiglin; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.util.AttributeHelper; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -30,18 +29,17 @@ public class KnightZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0xFDEF28 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0xFDEF28 ) + .addExperience( 2 ).multiplyRangedSpread( 1.2 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ).addToAttribute( Attributes.ARMOR, 10.0 ) + .addToAttribute( Attributes.ATTACK_DAMAGE, 6.0 ).addToRangedDamage( 6.0 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 0.8 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .addAttribute( Attributes.ARMOR, 10.0 ) - .addAttribute( Attributes.ATTACK_DAMAGE, 6.0 ) - .multAttribute( Attributes.MOVEMENT_SPEED, 0.8 ) - .build(); + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new ZombieSpeciesConfig( species, 0.1, 1.0 ); } @SpecialMob.LanguageProvider @@ -60,36 +58,24 @@ public class KnightZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return KnightZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public KnightZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 2; - } - - /** Override to change this entity's AI goals. */ - @Override - protected void registerVariantGoals() { - getSpecialData().rangedAttackDamage += 4.0F; - getSpecialData().rangedAttackSpread *= 1.2F; - } + public KnightZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Called during spawn finalization to set starting equipment. */ @Override protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { super.populateDefaultEquipmentSlots( difficulty ); + setItemSlot( EquipmentSlotType.HEAD, new ItemStack( Items.GOLDEN_HELMET ) ); setItemSlot( EquipmentSlotType.CHEST, new ItemStack( Items.GOLDEN_CHESTPLATE ) ); setItemSlot( EquipmentSlotType.LEGS, new ItemStack( Items.GOLDEN_LEGGINGS ) ); setItemSlot( EquipmentSlotType.FEET, new ItemStack( Items.GOLDEN_BOOTS ) ); } - - /** Override to change this entity's chance to spawn with a bow. */ - @Override - protected double getVariantBowChance() { return 0.1; } - - /** Override to change this entity's chance to spawn with a shield. */ - @Override - protected double getVariantShieldChance() { return 1.0; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/PlagueZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/PlagueZombifiedPiglinEntity.java index ea32aff..16fb635 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/PlagueZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/PlagueZombifiedPiglinEntity.java @@ -4,7 +4,6 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -12,13 +11,11 @@ import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -34,16 +31,11 @@ public class PlagueZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x8AA838 ); - //TODO theme - forest - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .multAttribute( Attributes.MOVEMENT_SPEED, 1.1 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x8AA838 ).theme( BestiaryInfo.Theme.FOREST ) + .uniqueTextureBaseOnly() + .addExperience( 1 ) + .multiplyAttribute( Attributes.MOVEMENT_SPEED, 1.1 ); } @SpecialMob.LanguageProvider @@ -62,13 +54,15 @@ public class PlagueZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return PlagueZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public PlagueZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 1; - } + public PlagueZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -86,12 +80,4 @@ public class PlagueZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity { } return arrow; } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "plague" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/VampireZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/VampireZombifiedPiglinEntity.java index 98f1bdd..79b0f27 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/VampireZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/VampireZombifiedPiglinEntity.java @@ -4,7 +4,6 @@ import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; -import fathertoast.specialmobs.common.util.AttributeHelper; import fathertoast.specialmobs.common.util.References; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; @@ -12,7 +11,6 @@ import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.ArrowEntity; @@ -21,7 +19,6 @@ import net.minecraft.item.Items; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; @@ -37,15 +34,11 @@ public class VampireZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity public static MobFamily.Species SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x000000, BestiaryInfo.BaseWeight.LOW ); - } - - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return AttributeHelper.of( _SpecialZombifiedPiglinEntity.createAttributes() ) - .addAttribute( Attributes.MAX_HEALTH, 10.0 ) - .build(); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x000000 ).weight( BestiaryInfo.DefaultWeight.LOW ) + .uniqueTextureWithOverlay() + .addExperience( 4 ) + .addToAttribute( Attributes.MAX_HEALTH, 10.0 ); } @SpecialMob.LanguageProvider @@ -67,13 +60,15 @@ public class VampireZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity @SpecialMob.Factory public static EntityType.IFactory getVariantFactory() { return VampireZombifiedPiglinEntity::new; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + //--------------- Variant-Specific Implementations ---------------- - public VampireZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - xpReward += 4; - } + public VampireZombifiedPiglinEntity( EntityType entityType, World world ) { super( entityType, world ); } /** Override to apply effects when this entity hits a target with a melee attack. */ @Override @@ -100,14 +95,4 @@ public class VampireZombifiedPiglinEntity extends _SpecialZombifiedPiglinEntity } return super.hurt( source, amount ); } - - private static final ResourceLocation[] TEXTURES = { - GET_TEXTURE_PATH( "vampire" ), - null, - GET_TEXTURE_PATH( "vampire_overlay" ) - }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/_SpecialZombifiedPiglinEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/_SpecialZombifiedPiglinEntity.java index e34541f..7776c20 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/_SpecialZombifiedPiglinEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/zombifiedpiglin/_SpecialZombifiedPiglinEntity.java @@ -3,7 +3,8 @@ package fathertoast.specialmobs.common.entity.zombifiedpiglin; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; -import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; +import fathertoast.specialmobs.common.config.species.ZombieSpeciesConfig; import fathertoast.specialmobs.common.entity.ISpecialMob; import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.SpecialMobData; @@ -33,7 +34,6 @@ import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.EffectInstance; import net.minecraft.util.DamageSource; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -55,15 +55,27 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme public static MobFamily.Species<_SpecialZombifiedPiglinEntity> SPECIES; @SpecialMob.BestiaryInfoSupplier - public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { - return new BestiaryInfo( 0x4C7129 ); + public static void getBestiaryInfo( BestiaryInfo.Builder bestiaryInfo ) { + bestiaryInfo.color( 0x4C7129 ) + .vanillaTextureBaseOnly( "textures/entity/piglin/zombified_piglin.png" ) + .experience( 5 ).undead().fireImmune() + .bowAttack( 2.0, 1.0, 0.8, 20, 15.0 ); } - @SpecialMob.AttributeCreator - public static AttributeModifierMap.MutableAttribute createAttributes() { - return ZombifiedPiglinEntity.createAttributes(); + protected static final double DEFAULT_BOW_CHANCE = 0.2; + protected static final double DEFAULT_SHIELD_CHANCE = 0.05; + + @SpecialMob.ConfigSupplier + public static SpeciesConfig createConfig( MobFamily.Species species ) { + return new ZombieSpeciesConfig( species, DEFAULT_BOW_CHANCE, DEFAULT_SHIELD_CHANCE ); } + /** @return This entity's species config. */ + public ZombieSpeciesConfig getConfig() { return (ZombieSpeciesConfig) getSpecies().config; } + + @SpecialMob.AttributeSupplier + public static AttributeModifierMap.MutableAttribute createAttributes() { return ZombifiedPiglinEntity.createAttributes(); } + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Zombified Piglin", @@ -81,12 +93,6 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme //--------------- Variant-Specific Breakouts ---------------- - public _SpecialZombifiedPiglinEntity( EntityType entityType, World world ) { - super( entityType, world ); - reassessWeaponGoal(); - getSpecialData().initialize(); - } - /** Called in the MobEntity.class constructor to initialize AI goals. */ @Override protected void registerGoals() { @@ -94,33 +100,12 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme AIHelper.removeGoals( goalSelector, ZombieAttackGoal.class ); AIHelper.replaceHurtByTarget( this, new SpecialHurtByTargetGoal( this, ZombifiedPiglinEntity.class ).setAlertOthers() ); - getSpecialData().rangedAttackDamage = 2.0F; - getSpecialData().rangedWalkSpeed = 0.8F; - getSpecialData().rangedAttackCooldown = 20; - getSpecialData().rangedAttackMaxCooldown = getSpecialData().rangedAttackCooldown; - getSpecialData().rangedAttackMaxRange = 15.0F; registerVariantGoals(); } /** Override to change this entity's AI goals. */ protected void registerVariantGoals() { } - /** Helper method to set the ranged attack AI more easily. */ - protected void disableRangedAI() { setRangedAI( 1.0, 20, 0.0F ); } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime ) { - getSpecialData().rangedWalkSpeed = (float) walkSpeed; - getSpecialData().rangedAttackCooldown = cooldownTime; - getSpecialData().rangedAttackMaxCooldown = cooldownTime; - } - - /** Helper method to set the ranged attack AI more easily. */ - protected void setRangedAI( double walkSpeed, int cooldownTime, float range ) { - setRangedAI( walkSpeed, cooldownTime ); - getSpecialData().rangedAttackMaxRange = range; - } - /** Override to change this entity's attack goal priority. */ protected int getVariantAttackPriority() { return 2; } @@ -128,20 +113,15 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme @Override protected void populateDefaultEquipmentSlots( DifficultyInstance difficulty ) { super.populateDefaultEquipmentSlots( difficulty ); - if( random.nextDouble() < getVariantBowChance() ) { //TODO config the default 20% chance + + if( getSpecialData().getRangedAttackMaxRange() > 0.0F && getConfig().ZOMBIES.bowEquipChance.rollChance( random ) ) { setItemSlot( EquipmentSlotType.MAINHAND, new ItemStack( Items.BOW ) ); } - else if( random.nextDouble() < getVariantShieldChance() ) { //TODO config the default 5% chance + else if( getConfig().ZOMBIES.shieldEquipChance.rollChance( random ) ) { setItemSlot( EquipmentSlotType.OFFHAND, new ItemStack( Items.SHIELD ) ); } } - /** Override to change this entity's chance to spawn with a bow. */ - protected double getVariantBowChance() { return getSpecialData().rangedAttackMaxRange > 0.0F ? 0.2 : 0.0; } - - /** Override to change this entity's chance to spawn with a shield. */ - protected double getVariantShieldChance() { return 0.05; } - /** Called to attack the target with a ranged attack. */ @Override public void performRangedAttack( LivingEntity target, float damageMulti ) { @@ -156,7 +136,7 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme final double dZ = target.getZ() - getZ(); final double dH = MathHelper.sqrt( dX * dX + dZ * dZ ); arrow.shoot( dX, dY + dH * 0.2, dZ, 1.6F, - getSpecialData().rangedAttackSpread * (14 - 4 * level.getDifficulty().getId()) ); + getSpecialData().getRangedAttackSpread() * (14 - 4 * level.getDifficulty().getId()) ); playSound( SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (random.nextFloat() * 0.4F + 0.8F) ); level.addFreshEntity( arrow ); @@ -165,7 +145,7 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme /** @return The arrow for this zombie to shoot. */ protected AbstractArrowEntity getArrow( ItemStack arrowItem, float damageMulti ) { return getVariantArrow( ProjectileHelper.getMobArrow( this, arrowItem, - damageMulti * getSpecialData().rangedAttackDamage ), arrowItem, damageMulti ); + damageMulti * getSpecialData().getRangedAttackDamage() ), arrowItem, damageMulti ); } /** Override to modify this entity's ranged attack projectile. */ @@ -198,11 +178,18 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme /** This entity's attack AI. */ private Goal currentAttackAI; + public _SpecialZombifiedPiglinEntity( EntityType entityType, World world ) { + super( entityType, world ); + reassessWeaponGoal(); + + getSpecialData().initialize(); + } + /** Called from the Entity.class constructor to define data watcher variables. */ @Override protected void defineSynchedData() { super.defineSynchedData(); - specialData = new SpecialMobData<>( this, SCALE, 1.0F ); + specialData = new SpecialMobData<>( this, SCALE ); } /** Called on spawn to initialize properties based on the world, difficulty, and the group it spawns with. */ @@ -210,7 +197,9 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme public ILivingEntityData finalizeSpawn( IServerWorld world, DifficultyInstance difficulty, SpawnReason spawnReason, @Nullable ILivingEntityData groupData, @Nullable CompoundNBT eggTag ) { groupData = super.finalizeSpawn( world, difficulty, spawnReason, groupData, eggTag ); + reassessWeaponGoal(); + return groupData; } @@ -229,9 +218,9 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme final SpecialMobData<_SpecialZombifiedPiglinEntity> data = getSpecialData(); final ItemStack weapon = getItemInHand( ProjectileHelper.getWeaponHoldingHand( this, item -> item instanceof BowItem ) ); - if( data.rangedAttackMaxRange > 0.0F && weapon.getItem() == Items.BOW ) { - currentAttackAI = new RangedBowAttackGoal<>( this, data.rangedWalkSpeed, - data.rangedAttackCooldown, data.rangedAttackMaxRange ); + if( data.getRangedAttackMaxRange() > 0.0F && weapon.getItem() == Items.BOW ) { + currentAttackAI = new RangedBowAttackGoal<>( this, data.getRangedWalkSpeed(), + data.getRangedAttackCooldown(), data.getRangedAttackMaxRange() ); } else { currentAttackAI = new ZombieAttackGoal( this, 1.0, false ); @@ -249,6 +238,11 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme @Override public SpecialMobData<_SpecialZombifiedPiglinEntity> getSpecialData() { return specialData; } + /** @return This entity's mob species. */ + @SpecialMob.SpeciesSupplier + @Override + public MobFamily.Species getSpecies() { return SPECIES; } + /** @return The experience that should be dropped by this entity. */ @Override public final int getExperience() { return xpReward; } @@ -257,16 +251,6 @@ public class _SpecialZombifiedPiglinEntity extends ZombifiedPiglinEntity impleme @Override public final void setExperience( int xp ) { xpReward = xp; } - static ResourceLocation GET_TEXTURE_PATH( String type ) { - return SpecialMobs.resourceLoc( SpecialMobs.TEXTURE_PATH + "zombifiedpiglin/" + type + ".png" ); - } - - private static final ResourceLocation[] TEXTURES = { new ResourceLocation( "textures/entity/piglin/zombified_piglin.png" ) }; - - /** @return All default textures for this entity. */ - @Override - public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //--------------- SpecialMobData Hooks ---------------- diff --git a/src/main/java/fathertoast/specialmobs/common/item/SyringeItem.java b/src/main/java/fathertoast/specialmobs/common/item/SyringeItem.java index 1a76ae4..8980e41 100644 --- a/src/main/java/fathertoast/specialmobs/common/item/SyringeItem.java +++ b/src/main/java/fathertoast/specialmobs/common/item/SyringeItem.java @@ -1,8 +1,11 @@ package fathertoast.specialmobs.common.item; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.Config; +import fathertoast.specialmobs.common.entity.MobHelper; import fathertoast.specialmobs.common.entity.creeper._SpecialCreeperEntity; import fathertoast.specialmobs.common.util.References; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.monster.CreeperEntity; import net.minecraft.entity.player.PlayerEntity; @@ -15,77 +18,80 @@ import net.minecraft.potion.Effects; import net.minecraft.util.*; import net.minecraft.world.World; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.function.Supplier; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault public class SyringeItem extends Item { - + public SyringeItem() { - super(new Item.Properties().stacksTo(1).rarity(Rarity.UNCOMMON).defaultDurability(5).setNoRepair().tab(ItemGroup.TAB_MISC)); + super( new Item.Properties().stacksTo( 1 ).rarity( Rarity.UNCOMMON ).defaultDurability( 5 ).setNoRepair().tab( ItemGroup.TAB_MISC ) ); } - + @SpecialMob.LanguageProvider public static String[] getTranslations( String langKey ) { return References.translations( langKey, "Syringe", "", "", "", "", "", "" );//TODO } - + @Override - public ActionResult use(World world, PlayerEntity player, Hand hand) { - ItemStack usedItem = player.getItemInHand(hand); - - if (!world.isClientSide) { - if (player.getCooldowns().isOnCooldown(usedItem.getItem())) { - return ActionResult.pass(usedItem); + public ActionResult use( World world, PlayerEntity player, Hand hand ) { + ItemStack usedItem = player.getItemInHand( hand ); + + if( !world.isClientSide ) { + if( player.getCooldowns().isOnCooldown( usedItem.getItem() ) ) { + return ActionResult.pass( usedItem ); } else { - player.addEffect(new EffectInstance(Effects.MOVEMENT_SPEED, 300, 2)); - player.addEffect(new EffectInstance(Effects.DOLPHINS_GRACE, 300)); - player.addEffect(new EffectInstance(Effects.CONFUSION, 400)); - world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BEE_STING, SoundCategory.PLAYERS, 0.9F, 1.0F); - usedItem.hurtAndBreak(1, player, (entity) -> { - entity.broadcastBreakEvent(hand); - }); - if (!player.isCreative()) { - player.getCooldowns().addCooldown(usedItem.getItem(), 1200); + player.addEffect( new EffectInstance( Effects.MOVEMENT_SPEED, 300, 2 ) ); + player.addEffect( new EffectInstance( Effects.DOLPHINS_GRACE, 300 ) ); + if( Config.MAIN.GENERAL.enableNausea.get() ) + player.addEffect( new EffectInstance( Effects.CONFUSION, 400 ) ); + world.playSound( null, player.getX(), player.getY(), player.getZ(), SoundEvents.BEE_STING, SoundCategory.PLAYERS, 0.9F, 1.0F ); + usedItem.hurtAndBreak( 1, player, ( entity ) -> entity.broadcastBreakEvent( hand ) ); + if( !player.isCreative() ) { + player.getCooldowns().addCooldown( usedItem.getItem(), 1200 ); } - return ActionResult.success(usedItem); + return ActionResult.success( usedItem ); } } - return ActionResult.fail(usedItem); + return ActionResult.fail( usedItem ); } - + @Override - public ActionResultType interactLivingEntity(ItemStack itemStack, PlayerEntity player, LivingEntity livingEntity, Hand hand) { - if (livingEntity instanceof CreeperEntity && !((CreeperEntity)livingEntity).isPowered()) { - if (player.getCooldowns().isOnCooldown(itemStack.getItem())) { + public ActionResultType interactLivingEntity( ItemStack itemStack, PlayerEntity player, LivingEntity livingEntity, Hand hand ) { + if( livingEntity instanceof CreeperEntity && !((CreeperEntity) livingEntity).isPowered() ) { + if( player.getCooldowns().isOnCooldown( itemStack.getItem() ) ) { return ActionResultType.PASS; } - livingEntity.getEntityData().set(CreeperEntity.DATA_IS_POWERED, true); - - if (livingEntity instanceof _SpecialCreeperEntity) { - if (livingEntity.getRandom().nextDouble() < 0.1D) { - ((_SpecialCreeperEntity)livingEntity).setSupercharged( true ); - } + + MobHelper.charge( (CreeperEntity) livingEntity ); + livingEntity.level.playSound( null, player.getX(), player.getY(), player.getZ(), SoundEvents.BEE_STING, SoundCategory.PLAYERS, 0.9F, 1.0F ); + itemStack.hurtAndBreak( 1, player, ( entity ) -> entity.broadcastBreakEvent( hand ) ); + if( !player.isCreative() ) { + player.getCooldowns().addCooldown( itemStack.getItem(), 1200 ); } - livingEntity.level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BEE_STING, SoundCategory.PLAYERS, 0.9F, 1.0F); - itemStack.hurtAndBreak(1, player, (entity) -> { - entity.broadcastBreakEvent(hand); - }); - if (!player.isCreative()) { - player.getCooldowns().addCooldown(itemStack.getItem(), 1200); - } - return ActionResultType.sidedSuccess(player.level.isClientSide); + return ActionResultType.sidedSuccess( player.level.isClientSide ); } return ActionResultType.PASS; } - + // Not enchantable @Override - public boolean isEnchantable(ItemStack itemStack) { + public boolean isEnchantable( ItemStack itemStack ) { return false; } - + // Very not enchantable @Override - public boolean isBookEnchantable(ItemStack stack, ItemStack book) { + public boolean isBookEnchantable( ItemStack stack, ItemStack book ) { return false; } -} + + // Really truly MEGA not enchantable + @SuppressWarnings( "unused" ) + public boolean isEvenALittleBitEnchantable( ItemStack stack, Supplier> objectSupplierSupplier ) { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java b/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java index c000531..616584c 100644 --- a/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java +++ b/src/main/java/fathertoast/specialmobs/common/util/AnnotationHelper.java @@ -3,6 +3,7 @@ package fathertoast.specialmobs.common.util; import fathertoast.specialmobs.common.bestiary.BestiaryInfo; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.config.species.SpeciesConfig; import fathertoast.specialmobs.datagen.loot.LootTableBuilder; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.EntityType; @@ -13,7 +14,10 @@ import net.minecraft.item.Item; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.lang.annotation.Annotation; -import java.lang.reflect.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * Provides helper methods to handle annotation processing through reflection. @@ -25,7 +29,7 @@ public final class AnnotationHelper { //--------------- PRETTY HELPER METHODS ---------------- - /** Creates an entity factory from a special mob species. Throws an exception if anything goes wrong. */ + /** Injects a reference to the special mob species into the species entity class. Throws an exception if anything goes wrong. */ public static void injectSpeciesReference( MobFamily.Species species ) { try { final Field field = getField( species.entityClass, SpecialMob.SpeciesReference.class ); @@ -36,21 +40,46 @@ public final class AnnotationHelper { } } - /** 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 ) { + /** Verifies the special mob species's entity class is overriding ISpecialMob#getSpecies(). Throws an exception if anything goes wrong. */ + public static void verifySpeciesSupplier( MobFamily.Species species ) { try { - return (BestiaryInfo) getMethod( species.entityClass, SpecialMob.BestiaryInfoSupplier.class ).invoke( null, entityType ); + getNonstaticMethod( species.entityClass, SpecialMob.SpeciesSupplier.class ); + } + catch( NoSuchMethodException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " does not override ISpecialMob#getSpecies()", ex ); + } + } + + /** Gets bestiary info from a special mob species. Throws an exception if anything goes wrong. */ + public static BestiaryInfo.Builder getBestiaryInfo( MobFamily.Species species, BestiaryInfo.Builder bestiaryInfo ) { + try { + getMethod( species.entityClass, SpecialMob.BestiaryInfoSupplier.class ).invoke( null, bestiaryInfo ); + return bestiaryInfo; } 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 ) { + /** Creates a species config from a special mob species. Throws an exception if anything goes wrong. */ + public static SpeciesConfig createConfig( MobFamily.Species species ) { try { - return ((AttributeModifierMap.MutableAttribute) getMethodOrSuper( species.entityClass, SpecialMob.AttributeCreator.class ) - .invoke( null )).build(); + final Method supplier = getMethodOrSuperOptional( species.entityClass, SpecialMob.ConfigSupplier.class ); + if( supplier == null ) { + return new SpeciesConfig( species ); + } + return (SpeciesConfig) supplier.invoke( null, species ); + } + catch( InvocationTargetException | IllegalAccessException ex ) { + throw new RuntimeException( "Entity class for " + species.name + " has invalid config creation method", ex ); + } + } + + /** Creates an attribute modifier map from a special mob species. Throws an exception if anything goes wrong. */ + public static AttributeModifierMap.MutableAttribute createAttributes( MobFamily.Species species ) { + try { + return (AttributeModifierMap.MutableAttribute) getMethodOrSuper( species.entityClass, SpecialMob.AttributeSupplier.class ) + .invoke( null ); } catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException ex ) { throw new RuntimeException( "Entity class for " + species.name + " has invalid attribute creation method", ex ); @@ -130,6 +159,20 @@ public final class AnnotationHelper { return null; } + /** + * @return Pulls a nonstatic method with a specific annotation from a class. + * @throws NoSuchMethodException if the method does not exist in the class. + */ + @SuppressWarnings( "UnusedReturnValue" ) + private static Method getNonstaticMethod( Class type, Class annotation ) throws NoSuchMethodException { + for( Method method : type.getDeclaredMethods() ) { + if( !Modifier.isStatic( method.getModifiers() ) && method.isAnnotationPresent( annotation ) ) + return method; + } + throw new NoSuchMethodException( String.format( "Could not find required nonstatic @%s annotated method in %s", + annotation.getSimpleName(), type.getName() ) ); + } + /** * @return Pulls a static method with a specific annotation from a class. * @throws NoSuchMethodException if the method does not exist in the class. @@ -148,6 +191,20 @@ public final class AnnotationHelper { * @throws NoSuchMethodException if the method does not exist in the class or any of its parents. */ private static Method getMethodOrSuper( Class type, Class annotation ) throws NoSuchMethodException { + final Method method = getMethodOrSuperOptional( type, annotation ); + if( method == null ) { + throw new NoSuchMethodException( String.format( "Could not find 'overridable' static @%s annotated method in %s or its parents", + annotation.getSimpleName(), type.getName() ) ); + } + return method; + } + + /** + * @return Pulls a static method with a specific annotation from a class, or its super class(es) if none is defined in the class, + * or null if the method does not exist. + */ + @Nullable + private static Method getMethodOrSuperOptional( Class type, Class annotation ) { Class currentType = type; while( currentType != LivingEntity.class ) { for( Method method : currentType.getDeclaredMethods() ) { @@ -156,21 +213,20 @@ public final class AnnotationHelper { } currentType = currentType.getSuperclass(); } - throw new NoSuchMethodException( String.format( "Could not find 'overridable' static @%s annotated method in %s or its parents", - annotation.getSimpleName(), type.getName() ) ); + return null; } - /** - * @return Pulls a constructor with a specific annotation from a class. - * @throws NoSuchMethodException if the constructor does not exist. - */ - private static Constructor getConstructor( Class type, Class annotation ) throws NoSuchMethodException { - for( Constructor constructor : type.getDeclaredConstructors() ) { - if( constructor.isAnnotationPresent( annotation ) ) - //noinspection unchecked - return (Constructor) constructor; - } - throw new NoSuchMethodException( String.format( "Could not find @%s annotated constructor in %s", - annotation.getSimpleName(), type.getName() ) ); - } + // /** + // * @return Pulls a constructor with a specific annotation from a class. + // * @throws NoSuchMethodException if the constructor does not exist. + // */ + // private static Constructor getConstructor( Class type, Class annotation ) throws NoSuchMethodException { + // for( Constructor constructor : type.getDeclaredConstructors() ) { + // if( constructor.isAnnotationPresent( annotation ) ) + // //noinspection unchecked + // return (Constructor) constructor; + // } + // throw new NoSuchMethodException( String.format( "Could not find @%s annotated constructor in %s", + // annotation.getSimpleName(), type.getName() ) ); + // } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/util/AttributeHelper.java b/src/main/java/fathertoast/specialmobs/common/util/AttributeHelper.java deleted file mode 100644 index e42f1a5..0000000 --- a/src/main/java/fathertoast/specialmobs/common/util/AttributeHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package fathertoast.specialmobs.common.util; - -import net.minecraft.entity.ai.attributes.Attribute; -import net.minecraft.entity.ai.attributes.AttributeModifierMap; -import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; - -/** An attribute builder used to easily tweak pre-existing attributes. */ -public class AttributeHelper { - /** @return An attribute builder used to easily tweak pre-existing attributes. */ - public static AttributeHelper of( AttributeModifierMap.MutableAttribute builder ) { - return new AttributeHelper( builder ); - } - - private final AttributeModifierMap.MutableAttribute underlyingBuilder; - - private AttributeHelper( AttributeModifierMap.MutableAttribute builder ) { - underlyingBuilder = builder; - } - - /** @return The current state of this builder. */ - public AttributeModifierMap.MutableAttribute build() { return underlyingBuilder; } - - /** - * Alters the entity's base attribute by adding an amount to it. - * Do NOT use this for move speed, instead use {@link #multAttribute(Attribute, double)} - * - * @param attribute the attribute to modify - * @param amount the amount to add to the attribute - */ - public AttributeHelper addAttribute( Attribute attribute, double amount ) { - final ModifiableAttributeInstance attributeInstance = underlyingBuilder.builder.get( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() + amount ); - return this; - } - - /** - * Alters the entity's base attribute by multiplying it by an amount. - * Mainly use this for move speed, for other attributes use {@link #addAttribute(Attribute, double)} - * - * @param attribute the attribute to modify - * @param amount the amount to multiply the attribute by - */ - public AttributeHelper multAttribute( Attribute attribute, double amount ) { - final ModifiableAttributeInstance attributeInstance = underlyingBuilder.builder.get( attribute ); - if( attributeInstance == null ) - throw new IllegalStateException( "Attempted to modify non-registered attribute " + attribute.getDescriptionId() ); - attributeInstance.setBaseValue( attributeInstance.getBaseValue() * amount ); - return this; - } -} \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/common/util/References.java b/src/main/java/fathertoast/specialmobs/common/util/References.java index d194192..910ed0d 100644 --- a/src/main/java/fathertoast/specialmobs/common/util/References.java +++ b/src/main/java/fathertoast/specialmobs/common/util/References.java @@ -1,17 +1,32 @@ package fathertoast.specialmobs.common.util; import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.StringNBT; +import java.util.UUID; + public final class References { + /** The speed boost to apply to baby mobs. */ + public static final AttributeModifier BABY_SPEED_BOOST = new AttributeModifier( UUID.fromString( "B9766B59-9566-4402-BC1F-2EE2A276D836" ), + "Baby speed boost", 0.5, AttributeModifier.Operation.MULTIPLY_BASE ); + + //--------------- BESTIARY REFLECTION ---------------- public static final String ENTITY_PACKAGE = "fathertoast." + SpecialMobs.MOD_ID + ".common.entity."; - public static final String VANILLA_REPLACEMENT_FORMAT = "%s_Special%sEntity"; - public static final String SPECIAL_VARIANT_FORMAT = "%s%sEntity"; + public static final String VANILLA_REPLACEMENT_FORMAT = "%s._Special%sEntity"; + public static final String SPECIAL_VARIANT_FORMAT = "%s.%sEntity"; + + public static final String TEXTURE_FORMAT = SpecialMobs.TEXTURE_PATH + "%s/%s%s.png"; + public static final String TEXTURE_BASE_SUFFIX = ""; + public static final String TEXTURE_EYES_SUFFIX = "_eyes"; + public static final String TEXTURE_OVERLAY_SUFFIX = "_overlay"; + public static final String TEXTURE_SHOOTING_SUFFIX = "_shooting"; + public static final String TEXTURE_SHOOTING_EYES_SUFFIX = "_shooting_eyes"; //--------------- BIT FLAGS ---------------- @@ -67,7 +82,7 @@ public final class References { // Creepers public static final String TAG_SUPERCHARGED = "Supercharged"; public static final String TAG_DRY_EXPLODE = "CannotExplodeWhileWet"; - public static final String TAG_WHEN_BURNING_EXPLODE = "ExplodesWhileBurning"; + public static final String TAG_WHILE_BURNING_EXPLODE = "ExplodesWhileBurning"; public static final String TAG_WHEN_SHOT_EXPLODE = "ExplodesWhenShot"; // Witches @@ -81,7 +96,11 @@ public final class References { // Baby-able families - Skeletons, Wither Skeletons public static final String TAG_IS_BABY = "IsBaby"; - // Spawner mobs TODO drowning creeper pufferfish cap? + // Shifting mobs - Corporeal Shift Ghast + public static final String TAG_IS_SHIFTED = "IsShifted"; + public static final String TAG_SHIFT_TIME = "ShiftTime"; + + // Spawner mobs public static final String TAG_BABIES = "Babies"; // Mother (Cave) Spider, Wilds Witch, Queen Ghast, Wildfire Blaze public static final String TAG_EXTRA_BABIES = "ExtraBabies"; // Splitting Creeper, Mother (Cave) Spider, Wilds Witch public static final String TAG_SUMMONS = "Summons"; // Undead Witch, Wilds Witch, Queen Ghast, Wildfire Blaze diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/flying.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/flying.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/flying.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/flying.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/flying_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/flying_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/flying_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/flying_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/mother.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/mother.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/mother.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/mother.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/mother_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/mother_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/mother_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/mother_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/web.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/web.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/web.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/web.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/web_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/web_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/web_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/web_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/witch.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/witch.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/witch.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/witch.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/cavespider/witch_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/cave_spider/witch_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/cavespider/witch_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/cave_spider/witch_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot.png b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shooting.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot.png rename to src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shooting.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shooting_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shooting_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/magmacube/bouncing.png b/src/main/resources/assets/specialmobs/textures/entity/magma_cube/bouncing.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/magmacube/bouncing.png rename to src/main/resources/assets/specialmobs/textures/entity/magma_cube/bouncing.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/magmacube/hardened.png b/src/main/resources/assets/specialmobs/textures/entity/magma_cube/hardened.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/magmacube/hardened.png rename to src/main/resources/assets/specialmobs/textures/entity/magma_cube/hardened.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/magmacube/sticky.png b/src/main/resources/assets/specialmobs/textures/entity/magma_cube/sticky.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/magmacube/sticky.png rename to src/main/resources/assets/specialmobs/textures/entity/magma_cube/sticky.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/magmacube/volatile.png b/src/main/resources/assets/specialmobs/textures/entity/magma_cube/volatile.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/magmacube/volatile.png rename to src/main/resources/assets/specialmobs/textures/entity/magma_cube/volatile.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire.png b/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire.png new file mode 100644 index 0000000..ce42947 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire.png differ diff --git a/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire_eyes.png new file mode 100644 index 0000000..8475359 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/skeleton/spitfire_eyes.png differ diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/brute.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/brute.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/brute.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/brute.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/brute_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/brute_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/brute_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/brute_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/fire.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/fire.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/fire.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/fire.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/fire_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/fire_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/fire_eyes.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/fire_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/gatling_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/gatling_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/gatling_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/gatling_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/ninja_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/ninja_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/ninja_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/ninja_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/sniper.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/sniper.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/sniper.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/sniper.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/witherskeleton/sniper_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/sniper_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/witherskeleton/sniper_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/sniper_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/fire.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/spitfire.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/fire.png rename to src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/spitfire.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/spitfire_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/spitfire_eyes.png new file mode 100644 index 0000000..1e05e3d Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/wither_skeleton/spitfire_eyes.png differ diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/brute.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/brute.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/brute.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/brute.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/brute_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/brute_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/brute_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/brute_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/hungry.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/hungry.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/hungry.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/hungry.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/plague.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/plague.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/plague.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/plague.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/vampire.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/vampire.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/vampire.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/vampire.png diff --git a/src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/vampire_overlay.png b/src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/vampire_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entity/zombifiedpiglin/vampire_overlay.png rename to src/main/resources/assets/specialmobs/textures/entity/zombified_piglin/vampire_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/flying.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/flying.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/flying.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/flying.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/flying_eyes.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/flying_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/flying_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/flying_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/mother.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/mother.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/mother.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/mother.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/mother_eyes.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/mother_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/mother_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/mother_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/web.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/web.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/web.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/web.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/web_eyes.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/web_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/web_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/web_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/witch.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/witch.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/witch.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/witch.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/witch_eyes.png b/src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/witch_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/cavespider/witch_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/cave_spider/witch_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/brute.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/brute.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/brute.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/brute.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/brute_overlay.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/brute_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/brute_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/brute_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/fire.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/fire.png new file mode 100644 index 0000000..4996804 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/fire.png differ diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/gatling_overlay.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/gatling_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/gatling_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/gatling_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/ninja_overlay.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/ninja_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/ninja_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/ninja_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/sniper.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/sniper.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/sniper.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/sniper.png diff --git a/src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/sniper_overlay.png b/src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/sniper_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityNEW/witherskeleton/sniper_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityNEW/wither_skeleton/sniper_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/flying.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/flying.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/flying.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/flying.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/flying_eyes.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/flying_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/flying_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/flying_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/mother.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/mother.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/mother.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/mother.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/mother_eyes.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/mother_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/mother_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/mother_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/web.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/web.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/web.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/web.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/web_eyes.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/web_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/web_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/web_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/witch.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/witch.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/witch.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/witch.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/witch_eyes.png b/src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/witch_eyes.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/cavespider/witch_eyes.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/cave_spider/witch_eyes.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/bouncing.png b/src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/bouncing.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/bouncing.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/bouncing.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/hardened.png b/src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/hardened.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/hardened.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/hardened.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/sticky.png b/src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/sticky.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/sticky.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/sticky.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/volatile.png b/src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/volatile.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/magmacube/volatile.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/magma_cube/volatile.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/brute.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/brute.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/brute.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/brute.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/brute_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/brute_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/brute_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/brute_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/fire.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/fire.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/fire.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/fire.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/gatling_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/gatling_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/gatling_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/gatling_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/ninja_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/ninja_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/ninja_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/ninja_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/sniper.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/sniper.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/sniper.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/sniper.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/sniper_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/sniper_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/witherskeleton/sniper_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/wither_skeleton/sniper_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/brute.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/brute.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/brute.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/brute.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/brute_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/brute_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/brute_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/brute_overlay.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/hungry.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/hungry.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/hungry.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/hungry.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/plague.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/plague.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/plague.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/plague.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/vampire.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/vampire.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/vampire.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/vampire.png diff --git a/src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/vampire_overlay.png b/src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/vampire_overlay.png similarity index 100% rename from src/main/resources/assets/specialmobs/textures/entityOLD/zombifiedpiglin/vampire_overlay.png rename to src/main/resources/assets/specialmobs/textures/entityOLD/zombified_piglin/vampire_overlay.png