当前位置:网站首页>Minecraft 1.18.1、1.18.2模组开发 23.3D动画盔甲制作
Minecraft 1.18.1、1.18.2模组开发 23.3D动画盔甲制作
2022-08-02 04:04:00 【Jay_fearless】
Minecraft 1.16.5模组开发3D盔甲
Minecraft 1.12.2模组开发3D盔甲
我们本次在1.18.2的版本中实现具有动画效果的3D盔甲
1.首先,为了实现这些效果,我们需要首先使用到一个模组:geckolib(下载地址)
找到项目的build.gradle
文件,在repositories
和dependencies
中添加依赖。
repositories {
//添加这个
maven { url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' }
}
dependencies {
minecraft 'net.minecraftforge:forge:1.18.2-40.1.0'
//添加这个
implementation fg.deobf('software.bernie.geckolib:geckolib-1.18-forge:3.0.18')
}
之后我们重新构建gradle项目
构建好了项目后在项目的Main类中添加一句geckolib的初始化语句:
Main.java
public Main() {
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
ItemInit.ITEMS.register(bus);
//添加GeckoLib初始化函数
GeckoLib.initialize();
MinecraftForge.EVENT_BUS.register(this);
}
2.之后,与之前的教程一样,我们需要在blockbench中制作一个模组中的3D盔甲:
进入软件后我们要找到一个插件按钮,然后再搜索栏中输入GeckoLib Animation Utils
,并下载这个插件
将我们制作好的生物实体进行模型转换工作,找到Convert Project
,之后选择Geckolib Animated Model
在这之后,你会发现你的生物实体栏多了一个Animate栏
,点击进去:
具体动作制作的视频:Blockbench动画制作
注:我们的盔甲的要完全按照这种进行制作:
在制作好所有的动画后我们导出模型和动画json文件。
3.模型制作完成,接下来需要制作我们的盔甲类
在items包中新建armor包 -> armor包中新建我们的套装类HeisensuitArmorItem
HeisensuitArmorItem.java
package com.joy187.re8joymod.items.armor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.init.EffectInit;
import com.joy187.re8joymod.init.ItemInit;
import com.joy187.re8joymod.util.CustomArmorMaterial;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ArmorMaterial;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import software.bernie.geckolib3.core.IAnimatable;
import software.bernie.geckolib3.core.PlayState;
import software.bernie.geckolib3.core.builder.AnimationBuilder;
import software.bernie.geckolib3.core.controller.AnimationController;
import software.bernie.geckolib3.core.event.predicate.AnimationEvent;
import software.bernie.geckolib3.core.manager.AnimationData;
import software.bernie.geckolib3.core.manager.AnimationFactory;
import software.bernie.geckolib3.item.GeoArmorItem;
public class HeisensuitArmorItem extends GeoArmorItem implements IAnimatable{
private AnimationFactory factory = new AnimationFactory(this);
public HeisensuitArmorItem(ArmorMaterial materialIn, EquipmentSlot slot, Properties builder) {
super(materialIn, slot, builder.tab(Main.TUTORIAL_TAB));
}
//动画状态机,判断每个时刻我们的盔甲的动画状态
@SuppressWarnings("unused")
private <P extends IAnimatable> PlayState predicate(AnimationEvent<P> event) {
// This is all the extradata this event carries. The livingentity is the entity
// that's wearing the armor. The itemstack and equipmentslottype are self
// explanatory.
List<EquipmentSlot> slotData = event.getExtraDataOfType(EquipmentSlot.class);
List<ItemStack> stackData = event.getExtraDataOfType(ItemStack.class);
LivingEntity livingEntity = event.getExtraDataOfType(LivingEntity.class).get(0);
// Always loop the animation but later on in this method we'll decide whether or
// not to actually play it
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.heisensuit.idle", true));
// If the living entity is an armorstand just play the animation nonstop
if (livingEntity instanceof ArmorStand) {
return PlayState.CONTINUE;
}
// The entity is a player, so we want to only play if the player is wearing the
// full set of armor
else if (livingEntity instanceof Player) {
Player player = (Player) livingEntity;
// Get all the equipment, aka the armor, currently held item, and offhand item
List<Item> equipmentList = new ArrayList<>();
player.getAllSlots().forEach((x) -> equipmentList.add(x.getItem()));
// 包含四个盔甲位置
List<Item> armorList = equipmentList.subList(2, 6);
//如果玩家穿上了所有的套装就会播放相应的动画
// Make sure the player is wearing all the armor. If they are, continue playing
// the animation, otherwise stop
//ItemInit.HEISEN_BOOTS.get(), ItemInit.HEISEN_LEGGINGS.get(),ItemInit.HEISEN_CHEST.get(), ItemInit.HEISEN_HEAD.get()
boolean isWearingAll = armorList
.containsAll(Arrays.asList(ItemInit.HEISEN_BOOTS.get(), ItemInit.HEISEN_LEGG.get()
,ItemInit.HEISEN_SUIT.get(), ItemInit.HEISEN_HEAD.get()));
return isWearingAll ? PlayState.CONTINUE : PlayState.STOP;
}
return PlayState.STOP;
}
//将我们的待机动画进行注册
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void registerControllers(AnimationData data) {
data.addAnimationController(new AnimationController(this, "controller", 20, this::predicate));
}
@Override
public AnimationFactory getFactory() {
return this.factory;
}
private static final Map<ArmorMaterial, MobEffectInstance> MATERIAL_TO_EFFECT_MAP =
(new ImmutableMap.Builder<ArmorMaterial, MobEffectInstance>())
.put(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT,
new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 100, 1)).build();
//穿上后给予效果
@Override
public void onArmorTick(ItemStack stack, Level world, Player player) {
if(!world.isClientSide()) {
//穿上头盔就给予一个药水效果
if(!player.getInventory().getArmor(3).isEmpty()) {
MobEffectInstance mapStatusEffect1 = new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 100, 2);
ArmorItem helmet = ((ArmorItem)player.getInventory().getArmor(3).getItem());
if(helmet.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
boolean hasPlayerEffect = player.hasEffect(mapStatusEffect1.getEffect());
if(!hasPlayerEffect) {
player.addEffect(new MobEffectInstance(mapStatusEffect1.getEffect(),mapStatusEffect1.getDuration(), mapStatusEffect1.getAmplifier()));
}
}
}
//穿上胸甲就给予一个药水效果
if(!player.getInventory().getArmor(2).isEmpty()) {
MobEffectInstance mapStatusEffect2 = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 100, 1);
ArmorItem breastplate = ((ArmorItem)player.getInventory().getArmor(2).getItem());
if(breastplate.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
boolean hasPlayerEffect = player.hasEffect(mapStatusEffect2.getEffect());
if(!hasPlayerEffect) {
player.addEffect(new MobEffectInstance(mapStatusEffect2.getEffect(),mapStatusEffect2.getDuration(), mapStatusEffect2.getAmplifier()));
}
}
}
//穿上护腿就给予一个药水效果
if(!player.getInventory().getArmor(1).isEmpty()) {
MobEffectInstance mapStatusEffect3 = new MobEffectInstance(MobEffects.SLOW_FALLING, 100, 1);
ArmorItem leggings = ((ArmorItem)player.getInventory().getArmor(1).getItem());
if(leggings.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
boolean hasPlayerEffect = player.hasEffect(mapStatusEffect3.getEffect());
if(!hasPlayerEffect) {
player.addEffect(new MobEffectInstance(mapStatusEffect3.getEffect(),mapStatusEffect3.getDuration(), mapStatusEffect3.getAmplifier()));
}
}
}
//穿上靴子就给予一个药水效果
if(!player.getInventory().getArmor(0).isEmpty()) {
MobEffectInstance mapStatusEffect4 = new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 100, 0);
ArmorItem boots = ((ArmorItem)player.getInventory().getArmor(0).getItem());
if(boots.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
boolean hasPlayerEffect = player.hasEffect(mapStatusEffect4.getEffect());
if(!hasPlayerEffect) {
player.addEffect(new MobEffectInstance(mapStatusEffect4.getEffect(),mapStatusEffect4.getDuration(), mapStatusEffect4.getAmplifier()));
}
}
}
}
}
}
之后我们需要在armor包中新建model包->model包中新建我们的盔甲的模型类ModelHeisensuit
:
ModelHeisensuit.java
package com.joy187.re8joymod.items.armor.model;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.items.armor.HeisensuitArmorItem;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib3.model.AnimatedGeoModel;
public class ModelHeisensuit extends AnimatedGeoModel<HeisensuitArmorItem> {
//盔甲模型文件地址
@Override
public ResourceLocation getModelLocation(HeisensuitArmorItem object) {
return new ResourceLocation(Main.MOD_ID, "geo/heisensuit.geo.json");
}
//盔甲材质文件地址
@Override
public ResourceLocation getTextureLocation(HeisensuitArmorItem object) {
return new ResourceLocation(Main.MOD_ID, "textures/models/armor/heisensuit_layer_1.png");
}
//盔甲动画文件地址
@Override
public ResourceLocation getAnimationFileLocation(HeisensuitArmorItem animatable) {
return new ResourceLocation(Main.MOD_ID, "animations/heisensuit.animation.json");
}
}
之后我们需要在armor包中新建render包->render包中新建我们的盔甲的模型类ModelHeisensuit
:
``
package com.joy187.re8joymod.items.armor.render;
import com.joy187.re8joymod.items.armor.HeisensuitArmorItem;
import com.joy187.re8joymod.items.armor.model.ModelHeisensuit;
import software.bernie.geckolib3.renderers.geo.GeoArmorRenderer;
public class RenderHeisensuit extends GeoArmorRenderer<HeisensuitArmorItem> {
//渲染盔甲穿在身上的每一个部位的效果
public RenderHeisensuit() {
super(new ModelHeisensuit());
//这里要和第二步你blockbench中建模的名称一一对应
this.headBone = "Head";
this.bodyBone = "chestplate";
this.rightArmBone = "rightArm";
this.leftArmBone = "leftArm";
this.rightLegBone = "rightLeg";
this.leftLegBone = "leftLeg";
this.rightBootBone = "rightBoot";
this.leftBootBone = "leftBoot";
}
}
4.在ClientModEventSubscriber
类中将我们的盔甲渲染类进行注册:
ClientModEventSubscriber.java
@Mod.EventBusSubscriber(modid = Main.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ClientModEventSubscriber extends ModEventSubscriber{
@OnlyIn(Dist.CLIENT)
@SubscribeEvent
public static void registerRenderers(final EntityRenderersEvent.AddLayers event) {
//渲染类进行注册
GeoArmorRenderer.registerArmorRenderer(HeisensuitArmorItem.class, new RenderHeisensuit());
}
}
5.在ItemInit类中将我们的盔甲进行声明,盔甲属性请参考之前的教程1.18.2 盔甲套装:
ItemInit.java
//头盔
public static final RegistryObject<HeisensuitArmorItem> HEISEN_HEAD = ITEMS.register("heisenhead",
() -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.HEAD, new Item.Properties()));
//胸甲
public static final RegistryObject<HeisensuitArmorItem> HEISEN_SUIT = ITEMS.register("heisensuit",
() -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.CHEST, new Item.Properties()));
//护腿
public static final RegistryObject<HeisensuitArmorItem> HEISEN_LEGG = ITEMS.register("heisenlegg",
() -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.LEGS, new Item.Properties()));
//靴子
public static final RegistryObject<HeisensuitArmorItem> HEISEN_BOOTS = ITEMS.register("heisenboots",
() -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.FEET, new Item.Properties()));
6.代码部分结束,之后来到材质包制作环节:
在resources\assets\你的modid
中的lang包中的en_us.json
添加盔甲的英文名称:
"item.re8joymod.heisenhead":"H",
"item.re8joymod.heisensuit":"H",
"item.re8joymod.heisenlegg":"Hei",
"item.re8joymod.heisenboots":"Heis",
在models\item
包中添加所有盔甲的模型文件:
头盔
heisenhead.json
{
"parent": "item/generated",
"textures": {
"layer0": "re8joymod:item/heisenhead"
}
}
胸甲
heisensuit.json
{
"parent": "item/generated",
"textures": {
"layer0": "re8joymod:item/heisensuit"
}
}
护腿
heisenlegg.json
{
"parent": "item/generated",
"textures": {
"layer0": "re8joymod:item/heisenlegg"
}
}
靴子
heisenboots.json
{
"parent": "item/generated",
"textures": {
"layer0": "re8joymod:item/heisenboots"
}
}
在textures\item
中添加盔甲的手持贴图:
在textures\models\armor
中添加盔甲的穿戴后贴图:
在assets\minecraft\textures\models\armor
中同样添加我们的穿戴后贴图:
新建一个geo包和animation包,把第二步中的模型和动画文件分别放进去
8.保存所有文件 -> 进行测试:
穿上盔甲,如果可以正常显示,就说明我们成功了!
边栏推荐
猜你喜欢
吴恩达机器学习系列课程笔记——第十五章:异常检测(Anomaly Detection)
DOM系列之 click 延时解决方案
[Win11] PowerShell cannot activate Conda virtual environment
科研笔记(八) 深度学习及其在 WiFi 人体感知中的应用(下)
8月1日“海豹数藏”将全网首发民族英雄林则徐《四行行书》数字藏品!
STM32 OLED显示屏
不会多线程还想进 BAT?精选 19 道多线程面试题,有答案边看边学
科研笔记(七) 基于路径规划和WiFi指纹定位的多目的地室内导航
被大厂强制毕业,两个月空窗期死背八股文,幸好上岸,不然房贷都还不上了
internship:数据库表和建立的实体类及对应的枚举类之间的联系示例
随机推荐
日本痴汉打赏女主播1.5亿,结果。。。
Your device is corrupt. It cant‘t be trusted and may not work propely.
高等数学(第七版)同济大学 总习题三(前10题) 个人解答
什么是接触电流怎么测?
ScholarOne Manuscripts submits journal LaTeX file and cannot convert PDF successfully!
UI自动化测试框架搭建——标记性能较差用例
SCI期刊最权威的信息查询步骤!
C# Thread IsBackground作用
Jetson Nano 2GB Developer Kit 安装说明
Computer Basics
复制延迟案例(3)-单调读
无主复制系统(3)-Quorum一致性的局限性
论文速读:Homography Loss for Monocular 3D Object Detection
斐波那契数列
Zabbix删除一些大表历史数据脚本
科研笔记(七) 基于路径规划和WiFi指纹定位的多目的地室内导航
The CCF brush topic tour - the first topic
Arduino框架下 ESP32看门狗使用示例
EasyCVR视频广场切换通道,视频播放协议异常的问题修复
1318_将ST link刷成jlink