Minecraft 1.18.1、1.18.2模组开发 03.生物实体

注:1.16.5的实体教程和本文基本类似,只是一些类中的函数名称有所不同。

我们今天在1.18.1的模组中添加一个生物实体

1.新建entity文件夹 -> 文件夹中新建一个model文件夹,一个render文件夹,一个我们的生物类(以EntityRe8Dimi.java为例)

cr0.jpg

我们本次要制作一个boss类怪物,类似于凋零,具有boss血条

EntityRe8Dimi.java

package com.joy187.re8joymod.entity;


import java.util.Random;
import java.util.function.Predicate;

import javax.annotation.Nullable;


import com.joy187.re8joymod.init.EntityInit;
import com.mojang.blaze3d.vertex.PoseStack.Pose;

import net.minecraft.client.renderer.EffectInstance;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.BossEvent;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
import net.minecraft.world.entity.animal.IronGolem;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.monster.Ravager;
import net.minecraft.world.entity.monster.ZombifiedPiglin;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraftforge.client.event.RenderGameOverlayEvent.BossInfo;
                                //我们的boss继承自劫掠兽
public class EntityRe8Dimi extends Ravager {
    //boss血条信息
    private final ServerBossEvent bossInfo = (ServerBossEvent)(new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true);
    private static final EntityDataAccessor<Integer> DATA_ID_INV = SynchedEntityData.defineId(EntityRe8Dimi.class, EntityDataSerializers.INT);
    //我们的boss不攻击类型为不死亡灵类的生物(凋零骷髅一类)
    private static final Predicate<LivingEntity> LIVING_ENTITY_SELECTOR = (p_31504_) -> {
        return p_31504_.getMobType() != MobType.UNDEAD && p_31504_.attackable();
     };
     
    public EntityRe8Dimi(EntityType<? extends Ravager> type, Level worldIn) {
        super(type, worldIn);
        this.xpReward = 150;
        this.isNonBoss();
        this.isSunSensitive();
        this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F);
    }
    //是否怕阳光
    protected boolean isSunSensitive() {
        return true;
    }

    public void aiStep() {


        super.aiStep();
    }
    //设置生物属性(最大血量、移动速度、攻击力、护甲值等)
    public static AttributeSupplier.Builder prepareAttributes() {
        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 120.0D).
                add(Attributes.MOVEMENT_SPEED, 0.28D).
                add(Attributes.FOLLOW_RANGE, 48.0D).
                add(Attributes.ARMOR, 8.0D).
                add(Attributes.ARMOR_TOUGHNESS, 10.0D).
                add(Attributes.KNOCKBACK_RESISTANCE, 0.85D).
                add(Attributes.ATTACK_DAMAGE, 9.0D);
    }
    //给生物设置攻击行为
    @Override
    protected void registerGoals() {
        super.registerGoals();
        this.goalSelector.addGoal(1, new RandomLookAroundGoal(this));
        this.goalSelector.addGoal(2, new LookAtPlayerGoal(this, Player.class, 8.0F));
        this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, LIVING_ENTITY_SELECTOR));
        this.addBehaviourGoals();
    }
    //给生物添加其行为
    protected void addBehaviourGoals() {
        this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
        this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers(ZombifiedPiglin.class));
        this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
        this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
        this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
//        this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, EntityEthan.class, true));
    }

    //生物攻击其他生物
    public boolean doHurtTarget(Entity entityIn) {
        if(!super.doHurtTarget(entityIn))
        {
            return false;
        }
        else{
            //如果攻击的对象是生物,就给这个对象一个凋零效果,持续1s(20ticks=1s)
            if(entityIn instanceof LivingEntity)
            {
                ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.WITHER, 20,0,true,true));
            }
            return true;
        }
    }
    
    //生物死亡音效
    @Override
    protected SoundEvent getDeathSound() {
//        Random ran = new Random();
//        int co = ran.nextInt(3);
//        if(co==0)
//        {
//            return SoundInit.ENTITY_DIMI_DEATH1.get();
//        }
//        else if(co==1) return SoundInit.ENTITY_DIMI_DEATH2.get();
        return SoundEvents.BEE_DEATH;
    }
    // 生物在玩家身边的音效
    protected SoundEvent getAmbientSound() {
//        Random ran = new Random();
//        int co = ran.nextInt(2);
//        if(co==0)
//        {
//            return SoundInit.ENTITY_DIMI_AMBIENT1.get();
//        }
//        return  SoundInit.ENTITY_DIMI_AMBIENT2.get();
        return SoundEvents.ZOMBIE_AMBIENT;
    }
//    生物受伤音效
//    @Override
//    protected SoundEvent getHurtSound(DamageSource source) {
//        Random ran = new Random();
//        int co = ran.nextInt(2);
//        if(co==0)
//        {
//            return SoundInit.ENTITY_DIMI_HURT1.get();
//        }
//        return SoundInit.ENTITY_DIMI_HURT2.get();
//    }

    protected float getStandingEyeHeight(Pose p_213348_1_, EntityDimensions p_213348_2_) {
        return 3F;
    }

    public void setInvulnerableTicks(int p_82215_1_) {
        this.entityData.set(DATA_ID_INV, p_82215_1_);
    }

    public void readAdditionalSaveData(CompoundTag p_70037_1_) {
        super.readAdditionalSaveData(p_70037_1_);
        this.setInvulnerableTicks(p_70037_1_.getInt("Invul"));
        if (this.hasCustomName()) {
            this.bossInfo.setName(this.getDisplayName());
        }

    }

    public void setCustomName(@Nullable Component p_200203_1_) {
        super.setCustomName(p_200203_1_);
        this.bossInfo.setName(this.getDisplayName());
    }

    protected void customServerAiStep() {
        super.customServerAiStep();

        if(this.isSunSensitive()){
            this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20*10,1,true,true));
        }

        Random ran = new Random();
        if(this.getHealth() >= 20.0F && this.getHealth()<=30.0F)
        {
            for(int i=0;i<5;i++)
                this.heal(1.0F*ran.nextFloat());
        }

        if(this.getHealth() >= 60.0F && this.getHealth()<=65.0F)
        {
            for(int i=0;i<4;i++)
                this.heal(1.5F*ran.nextFloat());
        }

//        if(this.getHealth() >= 0.1F && this.getHealth()<=10.0F)
//        {
//            this.convertTo(EntityDimi2,true);
//            EntityDimi2 e = new EntityDimi2(EntityInit.DIMI2.get(),this.level);
//            e.copyPosition(this);
//            this.level.addFreshEntity(e);
//            this.remove();
//
//        }

        this.bossInfo.setProgress(this.getHealth() / this.getMaxHealth());
    }


    public boolean isNonBoss()
    {
        return false;
    }
    //什么时候能看见boss血条
    public void startSeenByPlayer(ServerPlayer p_184178_1_) {
        super.startSeenByPlayer(p_184178_1_);
        this.bossInfo.addPlayer(p_184178_1_);
    }
    //什么时候看不见boss血条
    public void stopSeenByPlayer(ServerPlayer p_184203_1_) {
        super.stopSeenByPlayer(p_184203_1_);
        this.bossInfo.removePlayer(p_184203_1_);
    }


}
打开我们的blockbench -> 制作boss的3D模型 -> 导出制作好的模型

cr1.jpg

把我们的模型文件放入上面新建的model文件夹中

ModelRe8Dimi.java

package com.joy187.re8joymod.entity.model;

import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntityRe8Dimi;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;

import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.CubeDeformation;
import net.minecraft.client.model.geom.builders.CubeListBuilder;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;

// Made with Blockbench 4.1.3
// Exported for Minecraft version 1.17 with Mojang mappings
// Paste this class into your mod and generate all required imports


public class ModelRe8Dimi<T extends EntityRe8Dimi> extends EntityModel<T> {
	// This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into this model's constructor
	//注意这个皮肤路径
	public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(new ResourceLocation(Main.MOD_ID, "re8dimi"), "main");
	private final ModelPart Head;
	private final ModelPart Body;
	private final ModelPart RightArm;
	private final ModelPart LeftArm;
	private final ModelPart RightLeg;
	private final ModelPart LeftLeg;

	public ModelRe8Dimi(ModelPart root) {
		this.Head = root.getChild("Head");
		this.Body = root.getChild("Body");
		this.RightArm = root.getChild("RightArm");
		this.LeftArm = root.getChild("LeftArm");
		this.RightLeg = root.getChild("RightLeg");
		this.LeftLeg = root.getChild("LeftLeg");
	}

	public static LayerDefinition createBodyLayer() {
		MeshDefinition meshdefinition = new MeshDefinition();
		PartDefinition partdefinition = meshdefinition.getRoot();

		PartDefinition Head = partdefinition.addOrReplaceChild("Head", CubeListBuilder.create(), PartPose.offsetAndRotation(-0.4444F, -23.0556F, -3.3889F, -0.1047F, 0.0F, 0.0F));

		PartDefinition Head_r1 = Head.addOrReplaceChild("Head_r1", CubeListBuilder.create().texOffs(62, 33).addBox(-4.0F, -9.9993F, -6.9476F, 8.0F, 2.0F, 8.0F, new CubeDeformation(0.0F))
		.texOffs(51, 0).addBox(-7.0F, -7.9993F, -6.9476F, 14.0F, 2.0F, 8.0F, new CubeDeformation(0.0F))
		.texOffs(75, 43).addBox(-3.0F, -4.9993F, -10.9476F, 13.0F, 1.0F, 2.0F, new CubeDeformation(0.0F))
		.texOffs(87, 0).addBox(-12.0F, -4.9993F, -10.9476F, 9.0F, 2.0F, 2.0F, new CubeDeformation(0.0F))
		.texOffs(0, 77).addBox(-13.0F, -4.9993F, -10.9476F, 1.0F, 2.0F, 15.0F, new CubeDeformation(0.0F))
		.texOffs(68, 66).addBox(9.0F, -5.9993F, -9.9476F, 3.0F, 1.0F, 14.0F, new CubeDeformation(0.0F))
		.texOffs(0, 23).addBox(-12.0F, -5.9993F, -9.9476F, 21.0F, 2.0F, 14.0F, new CubeDeformation(0.0F))
		.texOffs(32, 80).addBox(-4.0F, -5.9993F, -6.9476F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.4444F, 3.0556F, 5.3889F, 0.1309F, 0.0F, 0.0F));

		PartDefinition Body = partdefinition.addOrReplaceChild("Body", CubeListBuilder.create().texOffs(56, 12).addBox(-6.0F, -16.0F, -6.0F, 12.0F, 10.0F, 11.0F, new CubeDeformation(0.0F))
		.texOffs(46, 65).addBox(-5.0F, -8.0F, -5.0F, 10.0F, 7.0F, 8.0F, new CubeDeformation(0.0F))
		.texOffs(0, 60).addBox(-6.0F, -3.0F, -7.0F, 12.0F, 6.0F, 11.0F, new CubeDeformation(0.0F))
		.texOffs(86, 33).addBox(-6.0F, -1.0F, 4.0F, 12.0F, 4.0F, 2.0F, new CubeDeformation(0.0F))
		.texOffs(44, 46).addBox(-8.0F, 2.0F, -7.0F, 16.0F, 5.0F, 14.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 0.0F, 0.0F));

		PartDefinition Body_r1 = Body.addOrReplaceChild("Body_r1", CubeListBuilder.create().texOffs(0, 39).addBox(-8.0F, -9.0F, -8.0F, 16.0F, 11.0F, 13.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 22.0F, 0.0F, 0.0F, 0.0436F, 0.0F));

		PartDefinition Body_r2 = Body.addOrReplaceChild("Body_r2", CubeListBuilder.create().texOffs(0, 0).addBox(-9.0F, -4.0F, -9.0F, 18.0F, 8.0F, 15.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 9.0F, 0.0F, 0.0F, -0.0436F, 0.0F));

		PartDefinition Body_r3 = Body.addOrReplaceChild("Body_r3", CubeListBuilder.create().texOffs(88, 65).addBox(-3.0F, -3.0F, -3.5F, 6.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -16.0F, -0.5F, 0.0F, 0.0436F, 0.0F));

		PartDefinition Body_r4 = Body.addOrReplaceChild("Body_r4", CubeListBuilder.create().texOffs(64, 81).addBox(-5.0F, -0.5F, -4.0F, 10.0F, 5.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -13.5654F, -6.5679F, 1.0036F, 0.0F, 0.0F));

		PartDefinition RightArm = partdefinition.addOrReplaceChild("RightArm", CubeListBuilder.create(), PartPose.offsetAndRotation(-9.0F, -10.0F, -1.0F, -0.2182F, 0.0F, 0.0F));

		PartDefinition RightArm_r1 = RightArm.addOrReplaceChild("RightArm_r1", CubeListBuilder.create().texOffs(90, 46).addBox(-3.9816F, -2.2586F, -3.0789F, 4.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(2.0F, -1.759F, -0.7541F, 0.0436F, -0.1745F, 1.4399F));

		PartDefinition Rightbacktlib = RightArm.addOrReplaceChild("Rightbacktlib", CubeListBuilder.create(), PartPose.offset(0.0F, 2.0F, 0.0F));

		PartDefinition RightArm_r2 = Rightbacktlib.addOrReplaceChild("RightArm_r2", CubeListBuilder.create().texOffs(0, 94).addBox(-5.0F, -6.9981F, -5.0872F, 4.0F, 7.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(3.0F, 0.644F, 3.0686F, 0.1745F, 0.0F, 0.0F));

		PartDefinition Rightfrontlib = Rightbacktlib.addOrReplaceChild("Rightfrontlib", CubeListBuilder.create(), PartPose.offset(0.0F, 0.0F, 0.0F));

		PartDefinition RightArm_r3 = Rightfrontlib.addOrReplaceChild("RightArm_r3", CubeListBuilder.create().texOffs(0, 38).addBox(-0.1511F, -7.7229F, -1.5045F, 0.0F, 12.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-3.0422F, 18.6266F, -6.0745F, -0.3054F, 0.0436F, 0.0873F));

		PartDefinition RightArm_r4 = Rightfrontlib.addOrReplaceChild("RightArm_r4", CubeListBuilder.create().texOffs(6, 38).addBox(-1.1702F, 4.3202F, -1.0721F, 0.0F, 11.0F, 1.0F, new CubeDeformation(0.0F))
		.texOffs(10, 0).addBox(-2.1702F, 3.3202F, -1.0721F, 1.0F, 2.0F, 1.0F, new CubeDeformation(0.0F))
		.texOffs(51, 3).addBox(-2.1702F, 3.3202F, -2.0721F, 1.0F, 2.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 6.8017F, -1.1584F, -0.3491F, 0.0F, 0.0873F));

		PartDefinition RightArm_r5 = Rightfrontlib.addOrReplaceChild("RightArm_r5", CubeListBuilder.create().texOffs(4, 39).addBox(0.8391F, -3.262F, -0.014F, 1.0F, 12.0F, 0.0F, new CubeDeformation(0.0F))
		.texOffs(9, 49).addBox(0.8391F, -3.262F, -0.014F, 1.0F, 2.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-1.0774F, 11.6115F, -4.6201F, -0.6545F, 0.0F, -0.1745F));

		PartDefinition RightArm_r6 = Rightfrontlib.addOrReplaceChild("RightArm_r6", CubeListBuilder.create().texOffs(2, 39).addBox(-0.1609F, -0.9749F, 0.5562F, 1.0F, 12.0F, 0.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-1.0774F, 11.6115F, -2.6201F, -0.3491F, 0.0F, -0.1745F));

		PartDefinition RightArm_r7 = Rightfrontlib.addOrReplaceChild("RightArm_r7", CubeListBuilder.create().texOffs(51, 0).addBox(-0.1609F, -2.6589F, 1.4355F, 1.0F, 2.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-1.0774F, 11.6115F, -4.6201F, -0.3491F, 0.0F, -0.1745F));

		PartDefinition RightArm_r8 = Rightfrontlib.addOrReplaceChild("RightArm_r8", CubeListBuilder.create().texOffs(0, 77).addBox(-2.0F, -6.6868F, -3.0746F, 3.0F, 10.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 6.8017F, -1.1584F, -0.3491F, 0.0F, 0.0F));

		PartDefinition nail = Rightfrontlib.addOrReplaceChild("nail", CubeListBuilder.create(), PartPose.offsetAndRotation(-1.3274F, 14.8615F, -4.6201F, -0.0436F, 0.0F, 0.0F));

		PartDefinition Rightnail_r1 = nail.addOrReplaceChild("Rightnail_r1", CubeListBuilder.create().texOffs(8, 38).addBox(-0.1281F, -0.5693F, -1.6828F, 0.0F, 11.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.25F, -3.25F, 0.0F, -0.1745F, -0.6109F, -0.4363F));

		PartDefinition RightArm_r9 = nail.addOrReplaceChild("RightArm_r9", CubeListBuilder.create().texOffs(51, 10).addBox(0.3164F, -2.4682F, -1.5852F, 1.0F, 2.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.25F, -3.25F, 0.0F, -0.3491F, 0.0F, -0.4363F));

		PartDefinition LeftArm = partdefinition.addOrReplaceChild("LeftArm", CubeListBuilder.create(), PartPose.offsetAndRotation(8.4442F, -8.8343F, -0.4302F, 0.2094F, 0.0F, 0.0F));

		PartDefinition LeftArm_r1 = LeftArm.addOrReplaceChild("LeftArm_r1", CubeListBuilder.create().texOffs(88, 85).addBox(-0.0164F, -3.2557F, -2.0027F, 4.0F, 6.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-0.5558F, -3.3343F, -0.4302F, 0.0436F, -0.2182F, -1.4399F));

		PartDefinition Leftlib = LeftArm.addOrReplaceChild("Leftlib", CubeListBuilder.create(), PartPose.offset(0.5558F, 2.5308F, -0.3245F));

		PartDefinition LeftArm_r2 = Leftlib.addOrReplaceChild("LeftArm_r2", CubeListBuilder.create().texOffs(17, 77).addBox(-2.0F, -5.4988F, -1.9302F, 4.0F, 7.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, -3.0F, 0.0F, -0.1745F, 0.0F, 0.0F));

		PartDefinition LeftArm_r3 = Leftlib.addOrReplaceChild("LeftArm_r3", CubeListBuilder.create().texOffs(16, 94).addBox(-1.0F, -9.076F, -3.2313F, 3.0F, 7.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 4.0829F, -5.6691F, -0.8727F, 0.0F, 0.0F));

		PartDefinition Leftfrontlib = Leftlib.addOrReplaceChild("Leftfrontlib", CubeListBuilder.create(), PartPose.offset(0.0F, 1.0F, -2.0F));

		PartDefinition LeftArm_r4 = Leftfrontlib.addOrReplaceChild("LeftArm_r4", CubeListBuilder.create().texOffs(0, 23).addBox(-2.0F, -9.076F, -3.2313F, 4.0F, 11.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 3.0829F, -3.6691F, -0.8727F, 0.0F, 0.0F));

		PartDefinition LeftArm_r5 = Leftfrontlib.addOrReplaceChild("LeftArm_r5", CubeListBuilder.create().texOffs(45, 46).addBox(0.4117F, 1.9822F, -3.162F, 1.0F, 3.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.3084F, 2.5147F, -3.6691F, -0.8727F, 0.0F, 0.3054F));

		PartDefinition LeftArm_r6 = Leftfrontlib.addOrReplaceChild("LeftArm_r6", CubeListBuilder.create().texOffs(45, 39).addBox(-1.0F, 2.0373F, -1.364F, 2.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 3.0829F, -3.6691F, -0.9599F, 0.0F, 0.0F));

		PartDefinition LeftArm_r7 = Leftfrontlib.addOrReplaceChild("LeftArm_r7", CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -0.6472F, -6.2955F, 1.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 7.0829F, -3.6691F, -0.8727F, 0.0F, 0.0F));

		PartDefinition RightLeg = partdefinition.addOrReplaceChild("RightLeg", CubeListBuilder.create(), PartPose.offsetAndRotation(-1.9F, 12.0F, 0.0F, 0.192F, 0.0F, 0.0349F));

		PartDefinition RightLeg_r1 = RightLeg.addOrReplaceChild("RightLeg_r1", CubeListBuilder.create().texOffs(64, 91).addBox(-3.9698F, -6.9878F, -1.7911F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(1.9F, 5.0F, 0.0F, -0.0873F, 0.0F, 0.0F));

		PartDefinition LeftLeg = partdefinition.addOrReplaceChild("LeftLeg", CubeListBuilder.create(), PartPose.offsetAndRotation(1.9F, 12.0F, 0.0F, -0.1745F, 0.0F, -0.0349F));

		PartDefinition LeftLeg_r1 = LeftLeg.addOrReplaceChild("LeftLeg_r1", CubeListBuilder.create().texOffs(91, 6).addBox(-0.0302F, -8.9988F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(-1.9F, 7.0F, 0.0F, 0.1745F, 0.0F, 0.0F));

		return LayerDefinition.create(meshdefinition, 128, 128);
	}

	@Override
	public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
		this.Head.yRot = netHeadYaw * 0.007453292F;
		this.Head.xRot = headPitch * 0.007453292F;
//		this.beak.xRot = this.head.xRot;
//		this.beak.yRot = this.head.yRot;
//		this.redThing.xRot = this.head.xRot;
//		this.redThing.yRot = this.head.yRot;
//		this.body.xRot = ((float)Math.PI / 2F);
		this.LeftArm.xRot = Mth.cos(limbSwing * 0.7662F) * 1.3F * limbSwingAmount;
		this.RightArm.xRot = Mth.cos(limbSwing * 0.7662F + (float)Math.PI) * 1.3F * limbSwingAmount;
		this.LeftLeg.xRot = Mth.cos(limbSwing * 0.5662F) * 1.4F * limbSwingAmount;
		this.RightLeg.xRot = Mth.cos(limbSwing * 0.5662F + (float)Math.PI) * 1.4F * limbSwingAmount;
	}

	public void setRotationAngle(ModelPart ModelPart, float x, float y, float z) {
		ModelPart.xRot = x;
		ModelPart.yRot= y;
		ModelPart.zRot = z;
	}
	
	@Override
	public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
		Head.render(poseStack, buffer, packedLight, packedOverlay);
		Body.render(poseStack, buffer, packedLight, packedOverlay);
		RightArm.render(poseStack, buffer, packedLight, packedOverlay);
		LeftArm.render(poseStack, buffer, packedLight, packedOverlay);
		RightLeg.render(poseStack, buffer, packedLight, packedOverlay);
		LeftLeg.render(poseStack, buffer, packedLight, packedOverlay);
	}
}
为了让我们的生物在游戏中可以显示出来,我们需要编写生物的渲染文件

在render文件夹中新建渲染类(以RenderRe8Dimi.java为例)
RenderRe8Dimi.java

package com.joy187.re8joymod.entity.render;

import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntityRe8Dimi;
import com.joy187.re8joymod.entity.model.ModelRe8Dimi;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.resources.ResourceLocation;


public class RenderRe8Dimi extends MobRenderer<EntityRe8Dimi, ModelRe8Dimi<EntityRe8Dimi>> {
    //注意这个路径,要和上面model文件中的路径保持一致
    public static final ResourceLocation TEXTURE = new ResourceLocation(Main.MOD_ID, "textures/entity/re8dimi.png");

    public RenderRe8Dimi(EntityRendererProvider.Context manager) {
        super(manager, new ModelRe8Dimi<>(manager.bakeLayer(ModelRe8Dimi.LAYER_LOCATION)), 0.7F);
     }
    
    @Override
    public ResourceLocation getTextureLocation(EntityRe8Dimi p_110775_1_) {
        return TEXTURE;
    }
}

2.在init包中新建一个EntityInit类用于初始化我们所有的生物

EntityInit.java

package com.joy187.re8joymod.init;


import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntityRe8Dimi;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class EntityInit {
	
    public static final DeferredRegister<EntityType<?>> ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.ENTITIES,
            Main.MOD_ID);

    //我们的生物类型为MONSTER(怪物),你可以定义其他类型MOB等,两个字符串要一样比如"re8dimi"
    public static final RegistryObject<EntityType<EntityRe8Dimi>> RE8DIMI = ENTITY_TYPES.register("re8dimi",
            () -> EntityType.Builder.of(EntityRe8Dimi::new, MobCategory.MONSTER).sized(0.8f,3.0f).setTrackingRange(30)
                    .build(new ResourceLocation(Main.MOD_ID, "re8dimi").toString()));
    
    //你可以往下续写
}

3.新建一个ClientModEventSubscriber类用于提交我们的渲染信息

ClientModEventSubscriber.java
package com.joy187.re8joymod;

import net.minecraftforge.fml.common.Mod;

import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;

import com.joy187.re8joymod.entity.EntityRe8Dimi;
import com.joy187.re8joymod.entity.model.ModelRe8Dimi;
import com.joy187.re8joymod.entity.render.RenderRe8Dimi;
import com.joy187.re8joymod.init.EntityInit;

import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;

@Mod.EventBusSubscriber(modid = Main.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ClientModEventSubscriber
{

    //将所有的生物的皮肤贴图信息写在这个函数里,有几个写几个
    @SubscribeEvent
    public static void onRegisterLayers(EntityRenderersEvent.RegisterLayerDefinitions event) {
        event.registerLayerDefinition(ModelRe8Dimi.LAYER_LOCATION, ModelRe8Dimi::createBodyLayer);
    }
    
    //将所有的生物的渲染信息写在这个函数里,有几个写几个
    @SubscribeEvent
    public static void onRegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
        event.registerEntityRenderer(EntityInit.RE8DIMI.get(), RenderRe8Dimi::new);
    }
    
    //将所有的生物的属性信息写在这个函数里,有几个写几个
    @SubscribeEvent
    public static void onAttributeCreate(EntityAttributeCreationEvent event) {
        event.put(EntityInit.RE8DIMI.get(), EntityRe8Dimi.prepareAttributes().build());
    }

}

4.在Main.java中添加:

	public Main() {
		IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();

		ItemInit.ITEMS.register(bus);
		BlockInit.BLOCKS.register(bus);
		
		//把生物初始化语句加入
		EntityInit.ENTITY_TYPES.register(bus);
		
		
		MinecraftForge.EVENT_BUS.register(this);
	}

5.在textures包下新建一个entity文件夹存放我们的生物皮肤贴图,将.png贴图放入其中:

cr2.jpg

在en_us.lang文件中添加游戏中的生物名称
"entity.re8joymod.re8dimi": "Alcina Dimitrescu",
怪物掉落物:

在resources\data\re8joymod\loot_tables下新建一个entities文件夹 -> 在文件夹中新建我们的生物掉落物.json文件(文件名称与EntityInit.java中保持一致)

{
  "type": "minecraft:entity",
  "pools": [
        {
            "rolls": 1.0,       
            "bonus_rolls": 0.0,
            "entries": [
                {
                    "type": "item",
                    "name": "re8joymod:blackfeather", //掉落物格式: 模组名称:物品名称
                    "weight": 6,
                    "functions": [
                        {
                            "function": "set_count",    //掉落个数
                            "count": {
                                "min": 0,   //最少掉几个
                                "max": 2    //最多掉几个
                            }
                        },
                        {
                            "function": "looting_enchant",
                            "count": {
                                "min": 0,
                                "max": 1
                            }
                        }
                    ]
                },
                {
                    "type": "item",
                    "weight": 5,
                    "name": "minecraft:totem_of_undying",   //原版掉落物格式: minecraft:物品名称
					"functions": [
                       {
                            "function": "set_count",
                            "count": {
                                "min": 2,
                                "max": 3
                            }
                       }
                   ]
                },
                {
                    "type": "item",
                    "weight": 5,
                    "name": "minecraft:nether_star",
					"functions": [
                       {
                            "function": "set_count",
                            "count": {
                                "min": 3,
                                "max": 5
                            }
                       }
                   ]
                }
             ]
        },
        {
			"name": "pool1",
            "rolls": 1,
            "entries": [
                {
                    "type": "item",
                    "name": "minecraft:bone",
                    "weight": 10
                },
                {
                    "type": "item",
                    "name": "minecraft:ghast_tear",
                    "weight": 4
                },
                {
                    "type": "item",
                    "weight": 5,
                    "name": "minecraft:nether_star",
					"functions": [
                       {
                            "function": "set_count",
                            "count": {
                                "min": 3,
                                "max": 5
                            }
                       }
                   ]
                }
            ]
        }
    ]
}

6.生物蛋制作

在ItemInit中添加:

        //刷怪蛋格式:ForgeSpawnEggItem(生物类,颜色1,颜色2,放在哪个物品栏)
public static final RegistryObject<Item> THIEF_EGG = ITEMS.register("re8dimi_spawn_egg", 
    		() -> new ForgeSpawnEggItem(EntityInit.RE8DIMI, 9577503, 13423070, new Item.Properties().tab(Main.TUTORIAL_TAB)));

在resources\assets\re8joymod\models\item中新建一个刷怪蛋.json文件(名称与ItemInit中的名称保持一致)
re8dimi_spawn_egg.json
{
	"parent": "item/template_spawn_egg"
}
在en_us.lang中添加语言信息:
"item.re8joymod.re8dimi_spawn_egg": "Alcina Dimitrescu Spawn Egg",

7.保存所有文件,刷新项目 -> 启动游戏

2022-02-22_21.39.28.png

我们的Boss成功生成!
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值