diff --git a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java index 50bce61..383f64d 100644 --- a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java +++ b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java @@ -31,7 +31,7 @@ public class ClientRegister { registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new ); //registerFamilyRenderers( MobFamily.SKELETON, SpecialSkeletonRenderer::new ); registerFamilyRenderers( MobFamily.SPIDER, SpecialSpiderRenderer::new ); - //registerFamilyRenderers( MobFamily.CAVE_SPIDER, SpecialSpiderRenderer::new ); + registerFamilyRenderers( MobFamily.CAVE_SPIDER, SpecialSpiderRenderer::new ); } private static void registerFamilyRenderers( MobFamily family, IRenderFactory renderFactory ) { diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java index a3b84c6..8870568 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java @@ -9,6 +9,7 @@ import net.minecraft.block.Block; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.monster.AbstractSkeletonEntity; +import net.minecraft.entity.monster.CaveSpiderEntity; import net.minecraft.entity.monster.CreeperEntity; import net.minecraft.entity.monster.SpiderEntity; import net.minecraft.util.math.BlockPos; @@ -76,10 +77,10 @@ public class MobFamily { "Spider", "spiders", 0x342D27, new EntityType[] { EntityType.SPIDER }, "Baby", "Desert", "Flying", "Giant", "Hungry", "Mother", "Pale", "Poison", "Web", "Witch" ); - // public static final MobFamily CAVE_SPIDER = new MobFamily<>( - // "CaveSpider", "cave spiders", 0x0C424E, new EntityType[] { EntityType.CAVE_SPIDER }, - // "Baby", "Flying", "Mother", "Web", "Witch" - // ); + public static final MobFamily CAVE_SPIDER = new MobFamily<>( + "CaveSpider", "cave spiders", 0x0C424E, new EntityType[] { EntityType.CAVE_SPIDER }, + "Baby", "Flying", "Mother", "Web", "Witch" + ); // public static final MobFamily SILVERFISH = new MobFamily<>( // "Silverfish", "silverfish", 0x6E6E6E, new EntityType[] { EntityType.SILVERFISH }, diff --git a/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java new file mode 100644 index 0000000..54ae89f --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/BabyCaveSpiderEntity.java @@ -0,0 +1,68 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +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; +import net.minecraftforge.fml.RegistryObject; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SpecialMob +public class BabyCaveSpiderEntity extends _SpecialCaveSpiderEntity { + + //--------------- Static Special Mob Hooks ---------------- + + @SpecialMob.TypeHolder + public static RegistryObject> ENTITY_TYPE; + + @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(); + } + + @SpecialMob.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Baby Cave Spider", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void buildLootTable( LootTableBuilder loot ) { + loot.addCommonDrop( "common", Items.STRING, 1 ); + } + + @SpecialMob.Constructor + public BabyCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().setBaseScale( 0.4F ); + getSpecialData().rangedAttackDamage -= 1.0F; + getSpecialData().rangedAttackMaxRange = 0.0F; + xpReward = 1; + } + + + //--------------- Variant-Specific Implementations ---------------- + + // None +} \ 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 new file mode 100644 index 0000000..dbc103a --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/FlyingCaveSpiderEntity.java @@ -0,0 +1,77 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.entity.ai.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; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SpecialMob +public class FlyingCaveSpiderEntity extends _SpecialCaveSpiderEntity { + + //--------------- Static Special Mob Hooks ---------------- + + @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(); + } + + @SpecialMob.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Flying Cave Spider", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void buildLootTable( LootTableBuilder loot ) { + addBaseLoot( loot ); + loot.addCommonDrop( "common", Items.FEATHER ); + } + + @SpecialMob.Constructor + public FlyingCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().setFallDamageMultiplier( 0.0F ); + xpReward += 2; + } + + + //--------------- Variant-Specific Implementations ---------------- + + /** Override to change this entity's AI goals. */ + @Override + protected void registerVariantGoals() { + 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 new file mode 100644 index 0000000..30b2a94 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/MotherCaveSpiderEntity.java @@ -0,0 +1,154 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +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.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; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SpecialMob +public class MotherCaveSpiderEntity extends _SpecialCaveSpiderEntity { + + //--------------- Static Special Mob Hooks ---------------- + + @SpecialMob.BestiaryInfoSupplier + public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { + return new BestiaryInfo( 0xB300B3 ); + } + + @SpecialMob.AttributeCreator + public static AttributeModifierMap.MutableAttribute createAttributes() { + return AttributeHelper.of( _SpecialCaveSpiderEntity.createAttributes() ) + .addAttribute( Attributes.MAX_HEALTH, 16.0 ) + .addAttribute( Attributes.ATTACK_DAMAGE, 3.0 ) + .addAttribute( Attributes.ARMOR, 6.0 ) + .build(); + } + + @SpecialMob.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Mother Cave Spider", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void buildLootTable( LootTableBuilder loot ) { + addBaseLoot( loot ); + loot.addUncommonDrop( "uncommon", Items.CAVE_SPIDER_SPAWN_EGG ); + } + + @SpecialMob.Constructor + public MotherCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + getSpecialData().setRegenerationTime( 30 ); + getSpecialData().rangedAttackDamage += 1.5F; + xpReward += 1; + babies = 2 + random.nextInt( 3 ); + extraBabies = 2 + random.nextInt( 3 ); + } + + + //--------------- Variant-Specific Implementations ---------------- + + /** The number of babies spawned on death. */ + private int babies; + /** The number of extra babies that can be spawned from hits. */ + private int extraBabies; + + /** @return Attempts to damage this entity; returns true if the hit was successful. */ + @Override + public boolean hurt( DamageSource source, float amount ) { + if( super.hurt( source, amount ) ) { + // Spawn babies when damaged + if( extraBabies > 0 && amount > 1.0F && level instanceof IServerWorld && random.nextFloat() < 0.33F ) { + extraBabies--; + spawnBaby( 0.66F, null ); + } + return true; + } + return false; + } + + /** Called each tick to update this entity while it's dead. */ + @Override + protected void tickDeath() { + if( deathTime == 19 && level instanceof IServerWorld ) { // At 19, the entity will be immediately removed upon call to super method + // Spawn babies on death + final int babiesToSpawn = babies + extraBabies; + ILivingEntityData groupData = null; + for( int i = 0; i < babiesToSpawn; i++ ) { + groupData = spawnBaby( 0.33F, groupData ); + } + playSound( SoundEvents.EGG_THROW, 1.0F, 2.0F / (random.nextFloat() * 0.4F + 0.8F) ); + } + + super.tickDeath(); + } + + /** Helper method to simplify spawning babies. */ + @Nullable + private ILivingEntityData spawnBaby( float speed, @Nullable ILivingEntityData groupData ) { + final BabyCaveSpiderEntity baby = BabyCaveSpiderEntity.ENTITY_TYPE.get().create( level ); + if( baby == null ) return groupData; + + baby.copyPosition( this ); + baby.yHeadRot = yRot; + baby.yBodyRot = yRot; + groupData = baby.finalizeSpawn( (IServerWorld) level, level.getCurrentDifficultyAt( blockPosition() ), + SpawnReason.MOB_SUMMONED, groupData, null ); + baby.setTarget( getTarget() ); + + baby.setDeltaMovement( + (random.nextDouble() - 0.5) * speed, + 0.2 + 0.5 * random.nextDouble(), // Used to cause floor clip bug; remove if it happens again + (random.nextDouble() - 0.5) * speed ); + baby.setOnGround( false ); + + level.addFreshEntity( baby ); + return groupData; + } + + /** Override to save data to this entity's NBT data. */ + @Override + public void addVariantSaveData( CompoundNBT saveTag ) { + saveTag.putByte( References.TAG_BABIES, (byte) babies ); + saveTag.putByte( References.TAG_EXTRA_BABIES, (byte) extraBabies ); + } + + /** Override to load data from this entity's NBT data. */ + @Override + public void readVariantSaveData( CompoundNBT saveTag ) { + if( saveTag.contains( References.TAG_BABIES, References.NBT_TYPE_NUMERICAL ) ) + babies = saveTag.getByte( References.TAG_BABIES ); + 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 new file mode 100644 index 0000000..5459469 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WebCaveSpiderEntity.java @@ -0,0 +1,119 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +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.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; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SpecialMob +public class WebCaveSpiderEntity extends _SpecialCaveSpiderEntity { + + //--------------- Static Special Mob Hooks ---------------- + + @SpecialMob.BestiaryInfoSupplier + public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { + return new BestiaryInfo( 0xE7E7E7, BestiaryInfo.BaseWeight.LOW ); + //TODO theme - forest + } + + @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.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Cave Weaver", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void buildLootTable( LootTableBuilder loot ) { + addBaseLoot( loot ); + loot.addUncommonDrop( "uncommon", Blocks.COBWEB ); + } + + @SpecialMob.Constructor + public WebCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + xpReward += 2; + webCount = 2 + random.nextInt( 5 ); + } + + + //--------------- Variant-Specific Implementations ---------------- + + /** The number of cobwebs this spider can place. */ + private int webCount; + + /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override + protected void onVariantAttack( Entity target ) { + if( !level.isClientSide() && webCount > 0 && target instanceof LivingEntity && !(target instanceof SpiderEntity) ) { + final BlockPos pos = target.blockPosition(); + if( !tryPlaceWeb( pos ) && target.getBbHeight() > 1.0F ) { + tryPlaceWeb( pos.above() ); + } + } + } + + /** Called when this entity dies to add drops regardless of loot table. */ + @Override + protected void dropCustomDeathLoot( DamageSource source, int looting, boolean killedByPlayer ) { + super.dropCustomDeathLoot( source, looting, killedByPlayer ); + tryPlaceWeb( blockPosition() ); + } + + /** @return Attempts to place a cobweb at the given position and returns true if successful. */ + private boolean tryPlaceWeb( BlockPos pos ) { + if( level.getBlockState( pos ).getMaterial().isReplaceable() ) { + level.setBlock( pos, Blocks.COBWEB.defaultBlockState(), References.SET_BLOCK_FLAGS ); + webCount--; + return true; + } + return false; + } + + /** Override to save data to this entity's NBT data. */ + @Override + public void addVariantSaveData( CompoundNBT saveTag ) { + saveTag.putByte( References.TAG_AMMO, (byte) webCount ); + } + + /** Override to load data from this entity's NBT data. */ + @Override + public void readVariantSaveData( CompoundNBT saveTag ) { + 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 new file mode 100644 index 0000000..9ee463e --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/WitchCaveSpiderEntity.java @@ -0,0 +1,87 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +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; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SpecialMob +public class WitchCaveSpiderEntity extends _SpecialCaveSpiderEntity { + + //--------------- Static Special Mob Hooks ---------------- + + @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(); + } + + @SpecialMob.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Witch Cave Spider", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void buildLootTable( LootTableBuilder loot ) { + addBaseLoot( loot ); + loot.addLootTable( "common", EntityType.WITCH.getDefaultLootTable() ); + } + + @SpecialMob.Constructor + public WitchCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + xpReward += 2; + } + + + //--------------- Variant-Specific Implementations ---------------- + + /** Override to apply effects when this entity hits a target with a melee attack. */ + @Override + protected void onVariantAttack( Entity target ) { + if( target instanceof LivingEntity ) { + ((LivingEntity) target).addEffect( MobHelper.nextWitchSpiderEffect( random, level, false ) ); + MobHelper.stealBuffEffect( this, (LivingEntity) target ); + } + } + + /** @return True if the effect can be applied to this entity. */ + @Override + public boolean canBeAffected( EffectInstance effect ) { + // 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 new file mode 100644 index 0000000..9efadc4 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/cavespider/_SpecialCaveSpiderEntity.java @@ -0,0 +1,231 @@ +package fathertoast.specialmobs.common.entity.cavespider; + +import fathertoast.specialmobs.common.bestiary.BestiaryInfo; +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; +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.monster.CaveSpiderEntity; +import net.minecraft.entity.player.PlayerEntity; +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.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 +@MethodsReturnNonnullByDefault +@SpecialMob +public class _SpecialCaveSpiderEntity extends CaveSpiderEntity implements ISpecialMob<_SpecialCaveSpiderEntity> { + + //--------------- Static Special Mob Hooks ---------------- + + @SpecialMob.BestiaryInfoSupplier + public static BestiaryInfo bestiaryInfo( EntityType.Builder entityType ) { + return new BestiaryInfo( 0xA80E0E ); + } + + @SpecialMob.AttributeCreator + public static AttributeModifierMap.MutableAttribute createAttributes() { + return CaveSpiderEntity.createAttributes(); + } + + @SpecialMob.LanguageProvider + public static String[] getTranslations( String langKey ) { + return References.translations( langKey, "Cave Spider", + "", "", "", "", "", "" );//TODO + } + + @SpecialMob.LootTableProvider + public static void addBaseLoot( LootTableBuilder loot ) { + loot.addLootTable( "main", EntityType.CAVE_SPIDER.getDefaultLootTable() ); + } + + @SpecialMob.Constructor + public _SpecialCaveSpiderEntity( EntityType entityType, World world ) { + super( entityType, world ); + specialData.initialize(); + } + + + //--------------- Variant-Specific Breakouts ---------------- + + /** Called in the MobEntity.class constructor to initialize AI goals. */ + @Override + protected void registerGoals() { + super.registerGoals(); + registerVariantGoals(); + } + + /** Override to change this entity's AI goals. */ + protected void registerVariantGoals() { } + + /** Called to melee attack the target. */ + @Override + public boolean doHurtTarget( Entity target ) { + if( super.doHurtTarget( target ) ) { + onVariantAttack( target ); + return true; + } + return false; + } + + /** Override to apply effects when this entity hits a target with a melee attack. */ + protected void onVariantAttack( Entity target ) { } + + /** Override to save data to this entity's NBT data. */ + public void addVariantSaveData( CompoundNBT saveTag ) { } + + /** Override to load data from this entity's NBT data. */ + public void readVariantSaveData( CompoundNBT saveTag ) { } + + + //--------------- Family-Specific Implementations ---------------- + + /** The parameter for special mob render scale. */ + private static final DataParameter SCALE = EntityDataManager.defineId( _SpecialCaveSpiderEntity.class, DataSerializers.FLOAT ); + + /** 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; + } + + + //--------------- ISpecialMob Implementation ---------------- + + private SpecialMobData<_SpecialCaveSpiderEntity> specialData; + + /** @return This mob's special data. */ + @Override + public SpecialMobData<_SpecialCaveSpiderEntity> getSpecialData() { return specialData; } + + /** @return The experience that should be dropped by this entity. */ + @Override + public final int getExperience() { return xpReward; } + + /** Sets the experience that should be dropped by this entity. */ + @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 ---------------- + + /** Called each tick to update this entity's movement. */ + @Override + public void aiStep() { + super.aiStep(); + getSpecialData().tick(); + } + + /** @return The eye height of this entity when standing. */ + @Override + protected float getStandingEyeHeight( Pose pose, EntitySize size ) { + return super.getStandingEyeHeight( pose, size ) * getSpecialData().getBaseScale() * (isBaby() ? 0.53448F : 1.0F); + } + + /** @return Whether this entity is immune to fire damage. */ + @Override + public boolean fireImmune() { return specialData.isImmuneToFire(); } + + /** Sets this entity on fire for a specific duration. */ + @Override + public void setRemainingFireTicks( int ticks ) { + if( !getSpecialData().isImmuneToBurning() ) super.setRemainingFireTicks( ticks ); + } + + /** @return True if this entity can be leashed. */ + @Override + public boolean canBeLeashed( PlayerEntity player ) { return !isLeashed() && getSpecialData().allowLeashing(); } + + /** Sets this entity 'stuck' inside a block, such as a cobweb or sweet berry bush. Mod blocks could use this as a speed boost. */ + @Override + public void makeStuckInBlock( BlockState block, Vector3d speedMulti ) { + if( specialData.canBeStuckIn( block ) ) super.makeStuckInBlock( block, speedMulti ); + } + + /** @return Called when this mob falls. Calculates and applies fall damage. Returns false if canceled. */ + @Override + public boolean causeFallDamage( float distance, float damageMultiplier ) { + return super.causeFallDamage( distance, damageMultiplier * getSpecialData().getFallDamageMultiplier() ); + } + + /** @return True if this entity should NOT trigger pressure plates or tripwires. */ + @Override + public boolean isIgnoringBlockTriggers() { return getSpecialData().ignorePressurePlates(); } + + /** @return True if this entity can breathe underwater. */ + @Override + public boolean canBreatheUnderwater() { return getSpecialData().canBreatheInWater(); } + + /** @return True if this entity can be pushed by (flowing) fluids. */ + @Override + public boolean isPushedByFluid() { return !getSpecialData().ignoreWaterPush(); } + + /** @return True if this entity takes damage while wet. */ + @Override + public boolean isSensitiveToWater() { return getSpecialData().isDamagedByWater(); } + + /** @return True if the effect can be applied to this entity. */ + @Override + public boolean canBeAffected( EffectInstance effect ) { return getSpecialData().isPotionApplicable( effect ); } + + /** Saves data to this entity's base NBT compound that is specific to its subclass. */ + @Override + public void addAdditionalSaveData( CompoundNBT tag ) { + super.addAdditionalSaveData( tag ); + + final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag ); + + getSpecialData().writeToNBT( saveTag ); + addVariantSaveData( saveTag ); + } + + /** Loads data from this entity's base NBT compound that is specific to its subclass. */ + @Override + public void readAdditionalSaveData( CompoundNBT tag ) { + super.readAdditionalSaveData( tag ); + + final CompoundNBT saveTag = SpecialMobData.getSaveLocation( tag ); + + getSpecialData().readFromNBT( saveTag ); + readVariantSaveData( saveTag ); + } +} \ 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 ab30294..6d6af4d 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/creeper/_SpecialCreeperEntity.java @@ -294,7 +294,7 @@ public class _SpecialCreeperEntity extends CreeperEntity implements ISpecialMob< public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //TODO--------------- SpecialMobData Hooks ---------------- + //--------------- SpecialMobData Hooks ---------------- /** Called each tick to update this entity's movement. */ @Override 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 b027e1b..3df91ec 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/skeleton/_SpecialSkeletonEntity.java @@ -287,7 +287,7 @@ public class _SpecialSkeletonEntity extends AbstractSkeletonEntity implements IS public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //TODO--------------- SpecialMobData Hooks ---------------- + //--------------- SpecialMobData Hooks ---------------- /** Called each tick to update this entity's movement. */ @Override 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 eb5ad34..b762874 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/HungrySpiderEntity.java @@ -104,6 +104,7 @@ public class HungrySpiderEntity extends _SpecialSpiderEntity { } } + /** Recalculates the modifiers associated with this entity's feeding level counters. */ private void updateFeedingLevels() { if( level != null && !level.isClientSide ) { final ModifiableAttributeInstance health = getAttribute( Attributes.MAX_HEALTH ); 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 2f37d4c..52a869d 100644 --- a/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java +++ b/src/main/java/fathertoast/specialmobs/common/entity/spider/_SpecialSpiderEntity.java @@ -146,7 +146,7 @@ public class _SpecialSpiderEntity extends SpiderEntity implements ISpecialMob<_S public ResourceLocation[] getDefaultTextures() { return TEXTURES; } - //TODO--------------- SpecialMobData Hooks ---------------- + //--------------- SpecialMobData Hooks ---------------- /** Called each tick to update this entity's movement. */ @Override diff --git a/src/main/java/fathertoast/specialmobs/common/util/References.java b/src/main/java/fathertoast/specialmobs/common/util/References.java index 25da97a..f6f6391 100644 --- a/src/main/java/fathertoast/specialmobs/common/util/References.java +++ b/src/main/java/fathertoast/specialmobs/common/util/References.java @@ -62,15 +62,15 @@ public final class References { public static final String TAG_IS_BABY = "IsBaby"; // Spawner mobs TODO drowning creeper pufferfish cap? - public static final String TAG_BABIES = "Babies"; // Mother Spd - public static final String TAG_EXTRA_BABIES = "ExtraBabies"; // Splitting Crp, Mother Spd + public static final String TAG_BABIES = "Babies"; // Mother (Cave) Spider + public static final String TAG_EXTRA_BABIES = "ExtraBabies"; // Splitting Creeper, Mother (Cave) Spider // Growing mobs - public static final String TAG_GROWTH_LEVEL = "GrowthLevel"; // Hungry Spd - public static final String TAG_HEALTH_STACKS = "HealthStacks"; // Hungry Spd + public static final String TAG_GROWTH_LEVEL = "GrowthLevel"; // Hungry Spider + public static final String TAG_HEALTH_STACKS = "HealthStacks"; // Hungry Spider // Misc. - public static final String TAG_AMMO = "Ammo"; // Web Spd + public static final String TAG_AMMO = "Ammo"; // Web (Cave) Spider //--------------- INTERNATIONALIZATION ----------------