diff --git a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java index 4e3df63..ee13ce0 100644 --- a/src/main/java/fathertoast/specialmobs/client/ClientRegister.java +++ b/src/main/java/fathertoast/specialmobs/client/ClientRegister.java @@ -3,9 +3,17 @@ package fathertoast.specialmobs.client; import fathertoast.specialmobs.client.renderer.entity.*; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.core.register.SMEntities; +import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; import fathertoast.specialmobs.common.entity.skeleton.NinjaSkeletonEntity; import fathertoast.specialmobs.common.entity.witherskeleton.NinjaWitherSkeletonEntity; import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.client.renderer.entity.SpriteRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.IRendersAsItem; import net.minecraft.entity.LivingEntity; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -15,6 +23,7 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.function.Supplier; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -24,10 +33,10 @@ public class ClientRegister { @SubscribeEvent public static void onClientSetup( FMLClientSetupEvent event ) { ClientEventHandler.registerConfigGUIFactory(); - registerEntityRenderers(); + registerEntityRenderers( event.getMinecraftSupplier() ); } - private static void registerEntityRenderers() { + private static void registerEntityRenderers( Supplier game ) { // Family-based renderers registerFamilyRenderers( MobFamily.CREEPER, SpecialCreeperRenderer::new ); registerFamilyRenderers( MobFamily.ZOMBIE, SpecialZombieRenderer::new ); @@ -47,6 +56,10 @@ public class ClientRegister { // Species overrides 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 ) { @@ -58,4 +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) { + ItemRenderer itemRenderer = minecraftSupplier.get().getItemRenderer(); + RenderingRegistry.registerEntityRenderingHandler(entityType, (renderManager) -> new SpriteRenderer<>(renderManager, itemRenderer, scale, fullBright)); + } } \ No newline at end of file diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastModel.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastModel.java new file mode 100644 index 0000000..c6be818 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastModel.java @@ -0,0 +1,55 @@ +package fathertoast.specialmobs.client.renderer.entity; + +import com.google.common.collect.ImmutableList; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.model.SegmentedModel; +import net.minecraft.client.renderer.model.ModelRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; + +import java.util.Random; +import java.util.function.Function; + +/** Copy of {@link net.minecraft.client.renderer.entity.model.GhastModel} */ +public class CorporealShiftGhastModel extends SegmentedModel { + private final ModelRenderer[] tentacles = new ModelRenderer[9]; + private final ImmutableList parts; + + public CorporealShiftGhastModel() { + ImmutableList.Builder builder = ImmutableList.builder(); + ModelRenderer modelrenderer = new ModelRenderer(this, 0, 0); + modelrenderer.addBox(-8.0F, -8.0F, -8.0F, 16.0F, 16.0F, 16.0F); + modelrenderer.y = 17.6F; + builder.add(modelrenderer); + Random random = new Random(1660L); + + for (int i = 0; i < this.tentacles.length; ++i) { + this.tentacles[i] = new ModelRenderer(this, 0, 0); + float f = (((float) (i % 3) - (float) (i / 3 % 2) * 0.5F + 0.25F) / 2.0F * 2.0F - 1.0F) * 5.0F; + float f1 = ((float) (i / 3) / 2.0F * 2.0F - 1.0F) * 5.0F; + int j = random.nextInt(7) + 8; + this.tentacles[i].addBox(-1.0F, 0.0F, -1.0F, 2.0F, (float) j, 2.0F); + this.tentacles[i].x = f; + this.tentacles[i].z = f1; + this.tentacles[i].y = 24.6F; + builder.add(this.tentacles[i]); + } + + this.parts = builder.build(); + } + + public void setRenderType(Function renderTypeFunc) { + this.renderType = renderTypeFunc; + } + + public void setupAnim(T ghast, float p_225597_2_, float p_225597_3_, float p_225597_4_, float p_225597_5_, float p_225597_6_) { + for (int i = 0; i < this.tentacles.length; ++i) { + this.tentacles[i].xRot = 0.2F * MathHelper.sin(p_225597_4_ * 0.3F + (float) i) + 0.4F; + } + } + + public Iterable parts() { + return this.parts; + } +} diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastRenderer.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastRenderer.java new file mode 100644 index 0000000..e29d24c --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/CorporealShiftGhastRenderer.java @@ -0,0 +1,53 @@ +package fathertoast.specialmobs.client.renderer.entity; + +import com.mojang.blaze3d.matrix.MatrixStack; +import fathertoast.specialmobs.client.renderer.entity.layers.SpecialGhastEyesLayer; +import fathertoast.specialmobs.client.renderer.entity.layers.SpecialMobEyesLayer; +import fathertoast.specialmobs.client.renderer.entity.misc.SMRenderTypes; +import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.entity.ISpecialMob; +import fathertoast.specialmobs.common.entity.SpecialMobData; +import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.util.ResourceLocation; + +import java.util.function.Function; + +public class CorporealShiftGhastRenderer extends MobRenderer> { + + private static final Function INCORPOREAL = (resourceLocation) -> SMRenderTypes.entityCutoutNoCullBlend(resourceLocation, SMRenderTypes.INCORPOREAL_ALPHA); + + private static final ResourceLocation EYES = SpecialMobs.resourceLoc("textures/entity/ghast/corporeal_shift_eyes.png"); + private static final ResourceLocation SHOOT_EYES = SpecialMobs.resourceLoc("textures/entity/ghast/corporeal_shift_shoot_eyes.png"); + + private final float baseShadowRadius; + + public CorporealShiftGhastRenderer(EntityRendererManager rendererManager) { + super(rendererManager, new CorporealShiftGhastModel<>(), 1.5F); + addLayer(new SpecialGhastEyesLayer<>(this, EYES, SHOOT_EYES )); + baseShadowRadius = shadowRadius; + } + + @Override + public void render(CorporealShiftGhastEntity ghast, float rotation, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight) { + model.renderType = ghast.isCorporeal() ? RenderType::entityCutoutNoCull : INCORPOREAL; + super.render(ghast, rotation, partialTicks, matrixStack, buffer, packedLight); + } + + + @Override + public ResourceLocation getTextureLocation( CorporealShiftGhastEntity entity ) { + final SpecialMobData data = ((ISpecialMob) entity).getSpecialData(); + return entity.isCharging() && data.hasOverlayTexture() ? data.getTextureOverlay() : data.getTexture(); + } + + @Override + protected void scale( CorporealShiftGhastEntity entity, MatrixStack matrixStack, float partialTick ) { + final float scale = 4.5F + ((ISpecialMob) entity).getSpecialData().getRenderScale(); + shadowRadius = baseShadowRadius * scale; + matrixStack.scale( scale, scale, scale ); + } +} diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/layers/SpecialGhastEyesLayer.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/layers/SpecialGhastEyesLayer.java new file mode 100644 index 0000000..eea53c5 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/layers/SpecialGhastEyesLayer.java @@ -0,0 +1,42 @@ +package fathertoast.specialmobs.client.renderer.entity.layers; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import fathertoast.specialmobs.common.core.SpecialMobs; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.IEntityRenderer; +import net.minecraft.client.renderer.entity.layers.AbstractEyesLayer; +import net.minecraft.client.renderer.entity.model.EntityModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.entity.monster.GhastEntity; +import net.minecraft.util.ResourceLocation; + +public class SpecialGhastEyesLayer> extends AbstractEyesLayer { + private final RenderType FALLBACK = RenderType.eyes( new ResourceLocation( "textures/entity/spider_eyes.png" ) ); + private final ResourceLocation eyes; + private final ResourceLocation shootEyes; + + + public SpecialGhastEyesLayer( IEntityRenderer renderer, ResourceLocation eyes, ResourceLocation shootEyes ) { + super( renderer ); + this.eyes = eyes; + this.shootEyes = shootEyes; + } + + @Override + public void render(MatrixStack matrixStack, IRenderTypeBuffer buffer, int packedLight, T ghast, float limbSwing, + float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch ) { + + IVertexBuilder vertexBuilder = buffer.getBuffer( RenderType.entityCutout(ghast.isCharging() ? shootEyes : eyes) ); + this.getParentModel().renderToBuffer( matrixStack, vertexBuilder, LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY, + 1.0F, 1.0F, 1.0F, 1.0F ); + } + + @Override + public RenderType renderType() { + SpecialMobs.LOG.warn( "Something is attempting to get eye layer 'render type' for some reason! :(" ); + return FALLBACK; + } +} diff --git a/src/main/java/fathertoast/specialmobs/client/renderer/entity/misc/SMRenderTypes.java b/src/main/java/fathertoast/specialmobs/client/renderer/entity/misc/SMRenderTypes.java new file mode 100644 index 0000000..8aee9ab --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/client/renderer/entity/misc/SMRenderTypes.java @@ -0,0 +1,24 @@ +package fathertoast.specialmobs.client.renderer.entity.misc; + +import net.minecraft.client.renderer.RenderState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +public class SMRenderTypes { + + public static RenderState.AlphaState INCORPOREAL_ALPHA = new RenderState.AlphaState(0.05F); + + public static RenderType entityCutoutNoCullBlend(ResourceLocation resourceLocation, RenderState.AlphaState alphaState) { + RenderType.State state = RenderType.State.builder() + .setTextureState(new RenderState.TextureState(resourceLocation, false, false)) + .setTransparencyState(RenderState.ADDITIVE_TRANSPARENCY) + .setDiffuseLightingState(RenderState.DIFFUSE_LIGHTING) + .setAlphaState(alphaState) + .setLightmapState(RenderState.LIGHTMAP) + .setOverlayState(RenderState.OVERLAY) + .createCompositeState(true); + + return RenderType.create("specialmobs_entity_cutout_no_cull_blend", DefaultVertexFormats.NEW_ENTITY, 7, 256, true, false, state); + } +} diff --git a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java index 97ff7c1..321c99a 100644 --- a/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java +++ b/src/main/java/fathertoast/specialmobs/common/bestiary/MobFamily.java @@ -97,7 +97,7 @@ public class MobFamily { public static final MobFamily GHAST = new MobFamily<>( "Ghast", "ghasts", 0xF9F9F9, new EntityType[] { EntityType.GHAST }, - "Baby", "Fighter", "King", "Queen", "Unholy" + "Baby", "Fighter", "King", "Queen", "Unholy", "CorporealShift" ); public static final MobFamily BLAZE = new MobFamily<>( 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 4f34ea6..72ccb0a 100644 --- a/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java +++ b/src/main/java/fathertoast/specialmobs/common/core/register/SMEntities.java @@ -2,8 +2,10 @@ package fathertoast.specialmobs.common.core.register; import fathertoast.specialmobs.common.bestiary.MobFamily; import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.entity.projectile.CorporealShiftFireballEntity; import fathertoast.specialmobs.common.util.AnnotationHelper; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; import net.minecraftforge.fml.RegistryObject; @@ -13,6 +15,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_fireball", + EntityType.Builder.of(CorporealShiftFireballEntity::new, EntityClassification.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10)); /** Registers an entity type to the deferred register. */ public static RegistryObject> register( String name, EntityType.Builder builder ) { diff --git a/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java new file mode 100644 index 0000000..56807f4 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/ghast/CorporealShiftGhastEntity.java @@ -0,0 +1,170 @@ +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.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 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; + +@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 ); + } + + @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", Items.POISONOUS_POTATO ); + } + + @SpecialMob.Factory + public static EntityType.IFactory getVariantFactory() { return CorporealShiftGhastEntity::new; } + + + //--------------- Variant-Specific Implementations ---------------- + + 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; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); + entityData.define(CORPOREAL, false); + } + + @Override + public void tick() { + super.tick(); + + if ( --shiftTime <= 0 ) { + if ( !level.isClientSide ) { + shiftTime = maxShiftTime; + entityData.set(CORPOREAL, !entityData.get(CORPOREAL)); + 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); + } + + public boolean isCorporeal() { + return entityData.get(CORPOREAL); + } + + /** 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 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( + getX() + lookVec.x, + getY( 0.5 ) + 0.5, + 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); + } + + /** Saves data to this entity's base NBT compound that is specific to its subclass. */ + @Override + public void addAdditionalSaveData( CompoundNBT tag ) { + super.addAdditionalSaveData( tag ); + tag.putInt("ShiftTime", shiftTime); + } + + /** Loads data from this entity's base NBT compound that is specific to its subclass. */ + @Override + public void readAdditionalSaveData( CompoundNBT tag ) { + super.readAdditionalSaveData( tag ); + + if (tag.contains("ShiftTime", Constants.NBT.TAG_ANY_NUMERIC)) { + shiftTime = tag.getInt("ShiftTime"); + } + } +} diff --git a/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java b/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java new file mode 100644 index 0000000..012e630 --- /dev/null +++ b/src/main/java/fathertoast/specialmobs/common/entity/projectile/CorporealShiftFireballEntity.java @@ -0,0 +1,147 @@ +package fathertoast.specialmobs.common.entity.projectile; + +import fathertoast.specialmobs.common.bestiary.SpecialMob; +import fathertoast.specialmobs.common.core.SpecialMobs; +import fathertoast.specialmobs.common.core.register.SMEntities; +import fathertoast.specialmobs.common.entity.ghast.CorporealShiftGhastEntity; +import fathertoast.specialmobs.common.util.References; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.projectile.AbstractFireballEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.fml.network.NetworkHooks; + +public class CorporealShiftFireballEntity extends AbstractFireballEntity { + + private static final DataParameter CORPOREAL = EntityDataManager.defineId(CorporealShiftFireballEntity.class, DataSerializers.BOOLEAN); + + public int explosionPower = 1; + private boolean shouldExplode = false; + + + 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()); + } + + @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); + } + + public boolean isCorporeal() { + return entityData.get(CORPOREAL); + } + + public void setCorporeal(boolean corporeal) { + entityData.set(CORPOREAL, corporeal); + } + + @Override + public void tick() { + super.tick(); + + 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); + remove(); + } + + + @Override + protected void onHit(RayTraceResult traceResult) { + super.onHit(traceResult); + + if (!level.isClientSide && isCorporeal()) { + shouldExplode = true; + } + } + + @Override + protected void onHitEntity(EntityRayTraceResult traceResult) { + super.onHitEntity(traceResult); + + if (!this.level.isClientSide) { + Entity target = traceResult.getEntity(); + Entity owner = getOwner(); + + if (!isCorporeal()) { + // TODO - Figure out why this is cringe + 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 { + 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()) { + return false; + } + shouldExplode = true; + return true; + } + else { + return super.hurt(damageSource, damage); + } + } + + @Override + public void addAdditionalSaveData(CompoundNBT compoundNBT) { + super.addAdditionalSaveData(compoundNBT); + compoundNBT.putInt("ExplosionPower", explosionPower); + compoundNBT.putBoolean("Corporeal", isCorporeal()); + } + + @Override + public void readAdditionalSaveData(CompoundNBT compoundNBT) { + super.readAdditionalSaveData(compoundNBT); + if (compoundNBT.contains("ExplosionPower", 99)) { + explosionPower = compoundNBT.getInt("ExplosionPower"); + } + entityData.set(CORPOREAL, compoundNBT.getBoolean("Corporeal")); + } + + @Override + public IPacket getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 0120535..4c8a2c7 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -2,7 +2,11 @@ # anything inside a final class, and private and/or static fields & methods. # Render stuff -public net.minecraft.client.renderer.WorldRenderer field_228415_m_ # renderBuffers +public-f net.minecraft.client.renderer.model.Model field_228281_q_ # renderType +public net.minecraft.client.renderer.RenderState field_228511_c_ # ADDITIVE_TRANSPARENCY +public net.minecraft.client.renderer.RenderState field_228532_x_ # DIFFUSE_LIGHTING +public net.minecraft.client.renderer.RenderState field_228528_t_ # LIGHTMAP +public net.minecraft.client.renderer.RenderState field_228530_v_ # OVERLAY # LIGHTMAP # Entity registration public net.minecraft.entity.EntityType field_233593_bg_ # immuneTo diff --git a/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift.png b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift.png new file mode 100644 index 0000000..16f93e5 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift.png differ diff --git a/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_eyes.png b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_eyes.png new file mode 100644 index 0000000..86dfe35 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_eyes.png differ 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_shoot.png new file mode 100644 index 0000000..97d2981 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot.png differ 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_shoot_eyes.png new file mode 100644 index 0000000..65178d1 Binary files /dev/null and b/src/main/resources/assets/specialmobs/textures/entity/ghast/corporeal_shift_shoot_eyes.png differ