Ninja skelly work

This commit is contained in:
Sarinsa 2022-06-26 19:26:03 +02:00 committed by Sarinsa
parent c3665d3807
commit 69d68219c4
8 changed files with 147 additions and 28 deletions

View file

@ -8,6 +8,7 @@ import fathertoast.specialmobs.client.renderer.entity.SpecialZombieRenderer;
import fathertoast.specialmobs.client.renderer.entity.*;
import fathertoast.specialmobs.common.bestiary.MobFamily;
import fathertoast.specialmobs.common.core.SpecialMobs;
import fathertoast.specialmobs.common.entity.skeleton.NinjaSkeletonEntity;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.entity.LivingEntity;
import net.minecraftforge.api.distmarker.Dist;
@ -28,7 +29,8 @@ public class ClientRegister {
public static void onClientSetup( FMLClientSetupEvent event ) {
registerEntityRenderers();
}
@SuppressWarnings("all")
private static void registerEntityRenderers() {
// Family-based renderers
registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new );
@ -40,11 +42,25 @@ public class ClientRegister {
registerFamilyRenderers( MobFamily.CAVE_SPIDER, SpecialSpiderRenderer::new );
registerFamilyRenderers( MobFamily.SILVERFISH, SpecialSilverfishRenderer::new );
registerFamilyRenderers( MobFamily.ENDERMAN, SpecialEndermanRenderer::new );
// Custom renderers
registerRenderer( NinjaSkeletonEntity.class, NinjaSkeletonRenderer::new);
}
private static <T extends LivingEntity> void registerFamilyRenderers( MobFamily<T> family, IRenderFactory<? super T> renderFactory ) {
private static <T extends LivingEntity> void registerFamilyRenderers(MobFamily<T> family, IRenderFactory<? super T> renderFactory ) {
RenderingRegistry.registerEntityRenderingHandler( family.vanillaReplacement.entityType.get(), renderFactory );
for( MobFamily.Species<? extends T> species : family.variants )
RenderingRegistry.registerEntityRenderingHandler( species.entityType.get(), renderFactory );
if ( !species.hasCustomRenderer )
RenderingRegistry.registerEntityRenderingHandler(species.entityType.get(), renderFactory);
}
private static <T extends LivingEntity> void registerRenderer(Class<T> entityClass, IRenderFactory<? super T> renderFactory) {
MobFamily.Species<T> species = MobFamily.findSpecies(entityClass);
if (species == null) {
SpecialMobs.LOG.error("Could not register renderer for entity class {}, as no belonging mob species was found.", entityClass.getSimpleName());
return;
}
RenderingRegistry.registerEntityRenderingHandler(species.entityType.get(), renderFactory);
}
}

View file

@ -0,0 +1,68 @@
package fathertoast.specialmobs.client.renderer.entity;
import com.mojang.blaze3d.matrix.MatrixStack;
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobEyesLayer;
import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobOverlayLayer;
import fathertoast.specialmobs.common.entity.ISpecialMob;
import fathertoast.specialmobs.common.entity.ai.INinja;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.entity.SkeletonRenderer;
import net.minecraft.client.renderer.entity.model.SkeletonModel;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.entity.monster.AbstractSkeletonEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.data.EmptyModelData;
public class NinjaSkeletonRenderer extends SkeletonRenderer {
private final float baseShadowRadius;
private BlockRendererDispatcher blockRenderer;
public NinjaSkeletonRenderer(EntityRendererManager rendererManager ) {
super( rendererManager );
baseShadowRadius = shadowRadius = shadowStrength = 0.0F;
this.blockRenderer = Minecraft.getInstance().getBlockRenderer();
addLayer( new SpecialMobEyesLayer<>( this ) );
addLayer( new SpecialMobOverlayLayer<>( this, new SkeletonModel<>( ) ) );
}
@Override
public void render(AbstractSkeletonEntity skeletonEntity, float f1, float f2, MatrixStack matrixStack, IRenderTypeBuffer buffer, int i) {
BlockState disguiseState = ((INinja)skeletonEntity).getDisguiseBlock();
if (disguiseState == null) {
super.render(skeletonEntity, f1, f2, matrixStack, buffer, i);
}
else {
renderBlockDisguise((AbstractSkeletonEntity & INinja) skeletonEntity, disguiseState, f1, f2, matrixStack, buffer, i);
}
}
private <T extends AbstractSkeletonEntity & INinja> void renderBlockDisguise(T ninja, BlockState state, float f1, float f2, MatrixStack matrixStack, IRenderTypeBuffer buffer, int i) {
matrixStack.pushPose();
matrixStack.translate(-0.5D, 0.0D, -0.5D);
this.blockRenderer.renderBlock(Blocks.LECTERN.defaultBlockState(), matrixStack, buffer, i, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
matrixStack.popPose();
}
@Override
public ResourceLocation getTextureLocation(AbstractSkeletonEntity entity ) {
return ((ISpecialMob<?>) entity).getSpecialData().getTexture();
}
@Override
protected void scale(AbstractSkeletonEntity entity, MatrixStack matrixStack, float partialTick ) {
super.scale( entity, matrixStack, partialTick );
final float scale = ((ISpecialMob<?>) entity).getSpecialData().getRenderScale();
shadowRadius = baseShadowRadius * scale;
matrixStack.scale( scale, scale, scale );
}
}

View file

@ -2,10 +2,12 @@ package fathertoast.specialmobs.common.bestiary;
import fathertoast.specialmobs.common.core.register.SMEntities;
import fathertoast.specialmobs.common.core.register.SMItems;
import fathertoast.specialmobs.common.entity.ISpecialMob;
import fathertoast.specialmobs.common.util.AnnotationHelper;
import fathertoast.specialmobs.common.util.References;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.monster.*;
@ -54,11 +56,11 @@ public class MobFamily<T extends LivingEntity> {
public static final MobFamily<AbstractSkeletonEntity> SKELETON = new MobFamily<>(
"Skeleton", "skeletons", 0xC1C1C1, new EntityType[] { EntityType.SKELETON, EntityType.STRAY },
"Brute", "Fire", "Gatling", "Giant", "Knight", /*"Ninja",*/ "Poison", "Sniper", /*"Spitfire",*/ "Stray"
"Brute", "Fire", "Gatling", "Giant", "Knight", "Ninja", "Poison", "Sniper", /*"Spitfire",*/ "Stray"
);
public static final MobFamily<AbstractSkeletonEntity> WITHER_SKELETON = new MobFamily<>(
"WitherSkeleton", "wither skeletons", 0x141414, new EntityType[] { EntityType.WITHER_SKELETON },
"Brute", "Gatling", "Giant", "Knight", /*"Ninja",*/ "Sniper"//, "Spitfire"
"Brute", "Gatling", "Giant", "Knight", "Ninja", "Sniper"//, "Spitfire"
);
public static final MobFamily<SlimeEntity> SLIME = new MobFamily<>(
@ -129,6 +131,16 @@ public class MobFamily<T extends LivingEntity> {
/** @return A list of all species. */
public static List<Species<?>> getAllSpecies() { return SPECIES_LIST; }
@SuppressWarnings("unchecked")
@Nullable
public static <T extends LivingEntity> Species<T> findSpecies(Class<T> entityClass) {
for (Species<?> species : getAllSpecies()) {
if (species.entityClass == entityClass)
return (Species<T>) species;
}
return null;
}
/** @return The family of mobs that can replace the passed entity; returns null if the entity is not replaceable. */
@Nullable
@ -237,11 +249,14 @@ public class MobFamily<T extends LivingEntity> {
public final RegistryObject<EntityType<T>> entityType;
/** This species's spawn egg item, wrapped in its registry object. */
public final RegistryObject<ForgeSpawnEggItem> spawnEgg;
/** Whether this species has a custom renderer. */
public final boolean hasCustomRenderer;
/** Constructs a new mob species. For vanilla replacements, the variant name is null. */
private Species( MobFamily<? super T> parentFamily, String packageRoot, @Nullable String variantName ) {
final boolean vanillaReplacement = variantName == null;
family = parentFamily;
specialVariantName = variantName;
name = vanillaReplacement ? parentFamily.name : variantName + parentFamily.name;
@ -257,9 +272,10 @@ public class MobFamily<T extends LivingEntity> {
// Initialize deferred registry objects
entityType = SMEntities.register( name.toLowerCase( Locale.ROOT ), entityTypeBuilder );
spawnEgg = SMItems.registerSpawnEgg( entityType, parentFamily.eggBaseColor, bestiaryInfo.eggSpotsColor );
hasCustomRenderer = AnnotationHelper.hasCustomRenderer( entityClass );
AnnotationHelper.injectEntityTypeHolder( this );
}
/** Finds the entity class based on a standard format. */
private Class<T> findClass( String format, String packageRoot ) {
try {

View file

@ -36,7 +36,9 @@ public @interface SpecialMob {
*/
@Retention( RetentionPolicy.RUNTIME )
@Target( ElementType.CONSTRUCTOR )
@interface Constructor { }
@interface Constructor {
boolean hasCustomRenderer() default false;
}
/**
* REQUIRED. This is called during registration to collect static properties of the mob needed for the bestiary

View file

@ -11,10 +11,10 @@ import javax.annotation.Nullable;
public interface INinja {
/** @return Whether this ninja is currently immobile. */
boolean isImmobile();
boolean isHiding();
/** Sets this ninja's immovable state. When activated, the entity is 'snapped' to the nearest block position. */
void setImmobile( boolean value );
void setHiding( boolean value );
/** @return The block being hidden (rendered) as, or null if not hiding. */
@Nullable

View file

@ -61,7 +61,7 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
Blocks.INFESTED_CRACKED_STONE_BRICKS, Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_CHISELED_STONE_BRICKS );
}
@SpecialMob.Constructor
@SpecialMob.Constructor(hasCustomRenderer = true)
public NinjaSkeletonEntity( EntityType<? extends _SpecialSkeletonEntity> entityType, World world ) {
super( entityType, world );
xpReward += 2;
@ -120,6 +120,8 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
if( !level.isClientSide() ) {
if( canHide ) {
//EntityAINinja.startHiding( this ); TODO
this.setHiding(true);
this.setDisguiseBlock(Blocks.DIRT.defaultBlockState());
}
else if( onGround && getDisguiseBlock() == null &&
(getTarget() == null || getTarget() instanceof PlayerEntity && ((PlayerEntity) getTarget()).isCreative()) ) {
@ -132,22 +134,24 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
// // Moves this entity.
// @Override TODO
// public void move( MoverType type, double x, double y, double z ) {
// if( isImmobile() && type != MoverType.PISTON ) {
// if( isHiding() && type != MoverType.PISTON ) {
// motionY = 0.0;
// }
// else {
// super.move( type, x, y, z );
// }
// }
//
// // Returns true if this entity should push and be pushed by other entities when colliding.
// @Override
// public boolean canBePushed() { return !isImmobile(); }
/** Returns true if this entity should push and be pushed by other entities when colliding. */
@Override
public boolean isPushable() {
return super.isPushable() && !isHiding();
}
/** Sets this entity on fire for a specific duration. */
@Override
public void setRemainingFireTicks( int ticks ) {
if( !isImmobile() ) super.setRemainingFireTicks( ticks );
if( !isHiding() ) super.setRemainingFireTicks( ticks );
}
/** Reveals this ninja and sets its target so that it doesn't immediately re-disguise itself. */
@ -186,12 +190,12 @@ public class NinjaSkeletonEntity extends _SpecialSkeletonEntity implements INinj
/** @return Whether this ninja is currently immobile. */
@Override
public boolean isImmobile() { return getEntityData().get( IS_HIDING ); }
public boolean isHiding() { return getEntityData().get( IS_HIDING ); }
/** Sets this ninja's immovable state. When activated, the entity is 'snapped' to the nearest block position. */
@Override
public void setImmobile( boolean value ) {
if( value != isImmobile() ) {
public void setHiding( boolean value ) {
if( value != isHiding() ) {
getEntityData().set( IS_HIDING, value );
if( value ) {
clearFire();

View file

@ -61,7 +61,7 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
Blocks.INFESTED_CRACKED_STONE_BRICKS, Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_CHISELED_STONE_BRICKS );
}
@SpecialMob.Constructor
@SpecialMob.Constructor(hasCustomRenderer = true)
public NinjaWitherSkeletonEntity( EntityType<? extends _SpecialWitherSkeletonEntity> entityType, World world ) {
super( entityType, world );
xpReward += 2;
@ -132,7 +132,7 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
// // Moves this entity.
// @Override TODO
// public void move( MoverType type, double x, double y, double z ) {
// if( isImmobile() && type != MoverType.PISTON ) {
// if( isHiding() && type != MoverType.PISTON ) {
// motionY = 0.0;
// }
// else {
@ -142,12 +142,12 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
//
// // Returns true if this entity should push and be pushed by other entities when colliding.
// @Override
// public boolean canBePushed() { return !isImmobile(); }
// public boolean canBePushed() { return !isHiding(); }
/** Sets this entity on fire for a specific duration. */
@Override
public void setRemainingFireTicks( int ticks ) {
if( !isImmobile() ) super.setRemainingFireTicks( ticks );
if( !isHiding() ) super.setRemainingFireTicks( ticks );
}
/** Reveals this ninja and sets its target so that it doesn't immediately re-disguise itself. */
@ -157,7 +157,7 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
}
private static final ResourceLocation[] TEXTURES = {
new ResourceLocation( "textures/entity/skeleton/skeleton.png" ),
new ResourceLocation( "textures/entity/skeleton/wither_skeleton.png" ),
null,
GET_TEXTURE_PATH( "ninja_overlay" )
};
@ -186,12 +186,12 @@ public class NinjaWitherSkeletonEntity extends _SpecialWitherSkeletonEntity impl
/** @return Whether this ninja is currently immobile. */
@Override
public boolean isImmobile() { return getEntityData().get( IS_HIDING ); }
public boolean isHiding() { return getEntityData().get( IS_HIDING ); }
/** Sets this ninja's immovable state. When activated, the entity is 'snapped' to the nearest block position. */
@Override
public void setImmobile( boolean value ) {
if( value != isImmobile() ) {
public void setHiding( boolean value ) {
if( value != isHiding() ) {
getEntityData().set( IS_HIDING, value );
if( value ) {
clearFire();

View file

@ -104,6 +104,19 @@ public final class AnnotationHelper {
throw new RuntimeException( "Entity class for " + species.name + " has invalid loot table builder method", ex );
}
}
/**
* Returns the boolean value for custom rendering from the target class' Constructor annotation.
* {@link SpecialMob.Constructor#hasCustomRenderer()}
*/
public static boolean hasCustomRenderer( Class<?> entityClass ) {
if (entityClass.isAnnotationPresent(SpecialMob.Constructor.class)) {
return entityClass.getDeclaredAnnotation(SpecialMob.Constructor.class).hasCustomRenderer();
}
else {
return false;
}
}
//--------------- RAW ANNOTATION METHODS ----------------