diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index ffb412b5..617041bd 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -56,7 +56,6 @@ import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.render.*; import net.minecraft.client.render.VertexConsumerProvider.Immediate; import net.minecraft.client.render.block.entity.BlockEntityRendererFactories; -import net.minecraft.client.render.entity.EmptyEntityRenderer; import net.minecraft.client.render.entity.FlyingItemEntityRenderer; import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.render.model.json.ModelTransformationMode; @@ -115,7 +114,7 @@ public interface URenderers { EntityRendererRegistry.register(UEntities.LOOT_BUG, LootBugEntityRenderer::new); EntityRendererRegistry.register(UEntities.TENTACLE, TentacleEntityRenderer::new); EntityRendererRegistry.register(UEntities.IGNOMINIOUS_BULB, IgnominiousBulbEntityRenderer::new); - EntityRendererRegistry.register(UEntities.SPECTER, EmptyEntityRenderer::new); + EntityRendererRegistry.register(UEntities.SPECTER, SpecterEntityRenderer::new); EntityRendererRegistry.register(UEntities.MIMIC, MimicEntityRenderer::new); BlockEntityRendererFactories.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/entity/SpecterEntityRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/entity/SpecterEntityRenderer.java new file mode 100644 index 00000000..763fd887 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/render/entity/SpecterEntityRenderer.java @@ -0,0 +1,41 @@ +package com.minelittlepony.unicopia.client.render.entity; + +import com.minelittlepony.unicopia.entity.mob.SpecterEntity; + +import net.minecraft.client.model.ModelPart; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.entity.BipedEntityRenderer; +import net.minecraft.client.render.entity.EntityRendererFactory.Context; +import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.util.Identifier; + +public class SpecterEntityRenderer extends BipedEntityRenderer { + + public SpecterEntityRenderer(Context context) { + super(context, new SpecterEntityModel(context.getPart(EntityModelLayers.PLAYER)), 0); + addFeature(new ArmorFeatureRenderer<>(this, + new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER_INNER_ARMOR)), + new BipedEntityModel<>(context.getPart(EntityModelLayers.PLAYER_OUTER_ARMOR)), + context.getModelManager())); + } + + @Override + public Identifier getTexture(SpecterEntity entity) { + return PlayerScreenHandler.BLOCK_ATLAS_TEXTURE; + } + + static class SpecterEntityModel extends BipedEntityModel { + public SpecterEntityModel(ModelPart root) { + super(root); + } + + @Override + public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { + // noop + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java index 91f9b407..7d99db13 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/SpecterEntity.java @@ -2,11 +2,15 @@ package com.minelittlepony.unicopia.entity.mob; import org.jetbrains.annotations.Nullable; +import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.particle.FootprintParticleEffect; import com.minelittlepony.unicopia.particle.ParticleUtils; +import net.minecraft.entity.EntityData; import net.minecraft.entity.EntityType; +import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnReason; import net.minecraft.entity.ai.goal.ActiveTargetGoal; import net.minecraft.entity.ai.goal.LookAroundGoal; import net.minecraft.entity.ai.goal.LookAtEntityGoal; @@ -19,12 +23,18 @@ import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.particle.ParticleTypes; import net.minecraft.registry.tag.BlockTags; import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.Difficulty; import net.minecraft.world.GameRules; +import net.minecraft.world.LocalDifficulty; +import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.World; public class SpecterEntity extends HostileEntity { @@ -44,21 +54,21 @@ public class SpecterEntity extends HostileEntity { @Override protected void initGoals() { - this.goalSelector.add(1, new SwimGoal(this)); - this.goalSelector.add(4, new MeleeAttackGoal(this, 1.0, true)); - this.goalSelector.add(5, new WanderAroundFarGoal(this, 0.8)); - this.goalSelector.add(6, new LookAtEntityGoal(this, PlayerEntity.class, 8.0f)); - this.goalSelector.add(6, new LookAroundGoal(this)); - this.targetSelector.add(1, new RevengeGoal(this)); - this.targetSelector.add(2, new TargetGoal<>(this, PlayerEntity.class)); + goalSelector.add(1, new SwimGoal(this)); + goalSelector.add(4, new MeleeAttackGoal(this, 1.0, true)); + goalSelector.add(5, new WanderAroundFarGoal(this, 0.8)); + goalSelector.add(6, new LookAtEntityGoal(this, PlayerEntity.class, 8.0f)); + goalSelector.add(6, new LookAroundGoal(this)); + targetSelector.add(1, new RevengeGoal(this)); + //this.targetSelector.add(2, new TargetGoal<>(this, PlayerEntity.class)); } - @SuppressWarnings("deprecation") @Override public void tick() { Vec3d prevPosition = getPos(); super.tick(); - if (getBrightnessAtEyes() < 0.5F || getTarget() != null) { + + if (getTarget() != null) { ParticleUtils.spawnParticles(ParticleTypes.AMBIENT_ENTITY_EFFECT, this, 6); if (getWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) { @@ -66,6 +76,8 @@ public class SpecterEntity extends HostileEntity { getWorld().breakBlock(getBlockPos(), true); } } + + } if (!hasVehicle() && isOnGround()) { @@ -83,6 +95,23 @@ public class SpecterEntity extends HostileEntity { } } + @Override + public void setAttacker(@Nullable LivingEntity attacker) { + if (!getWorld().isClient && attacker != null) { + getWorld().getEntitiesByClass(SpecterEntity.class, this.getBoundingBox().expand(5), e -> e != this && e.getTarget() == null).forEach(specter -> { + specter.notifyPartyAttacker(this, attacker); + }); + } + super.setAttacker(attacker); + } + + private void notifyPartyAttacker(SpecterEntity sender, @Nullable LivingEntity attacker) { + super.setAttacker(attacker); + getNavigation().stop(); + getNavigation().startMovingTo(sender, 3); + playSound(USounds.Vanilla.ENTITY_VEX_HURT, 1, 0.5F); + } + @Override public float getSoundPitch() { return super.getSoundPitch() * 0.3F; @@ -104,6 +133,27 @@ public class SpecterEntity extends HostileEntity { } + @Nullable + @Override + public EntityData initialize(ServerWorldAccess world, LocalDifficulty difficulty, SpawnReason spawnReason, @Nullable EntityData data, @Nullable NbtCompound entityNbt) { + data = super.initialize(world, difficulty, spawnReason, data, entityNbt); + Random random = world.getRandom(); + float diff = difficulty.getClampedLocalDifficulty(); + setCanPickUpLoot(random.nextFloat() < 0.55F * diff); + initEquipment(random, difficulty); + return data; + } + + @Override + protected void initEquipment(Random random, LocalDifficulty localDifficulty) { + if (random.nextFloat() < (getWorld().getDifficulty() == Difficulty.HARD ? 0.05F : 0.01F)) { + if (random.nextFloat() < (getWorld().getDifficulty() == Difficulty.HARD ? 0.5F : 0.1F)) { + super.initEquipment(random, localDifficulty); + } + equipStack(EquipmentSlot.MAINHAND, (random.nextInt(3) == 0 ? Items.STONE_SWORD : Items.WOODEN_SWORD).getDefaultStack()); + } + } + static class TargetGoal extends ActiveTargetGoal { public TargetGoal(SpecterEntity specter, Class targetEntityClass) { super(specter, targetEntityClass, true);