Minecraft(我的世界)中文论坛

 找回密码
 注册(register)

!header_login!

只需一步,立刻登录

查看: 1771|回复: 15

[Mod开发教程] Minecraft 1.12.2模组开发 霰弹枪

[复制链接]
我才是Joy 当前离线
积分
961
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-4-13
查看详细资料
发表于 2021-6-15 19:21:02 | 显示全部楼层 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 我才是Joy 于 2021-7-28 10:13 编辑

Minecraft 1.12.2模组开发(二十三) 霰弹枪

我们的生化8模组更新到1.16.5版本啦!!!
生化8 mod下载地址

Minecraft 1.12.2 全套模组开发教程地址

我们今天在世界中创造一把属于自己的霰弹枪

1.制作枪械和子弹的模型(blockbench) 下载地址

注意调整武器的手中方位(每个槽位都要调!)

2.在ModItems中添加我们刚刚制作的两个物品的信息
    public static final Item W870 = new ItemM1897("w870", Main.ITEM_TAB);
    public static final Item M1897B = new ItemM1897B("m1897b", Main.ITEM_TAB);



3.在items包中新建ItemM1897类(霰弹枪类)


ItemM1897.java 中编写代码
package com.Joy187.newmod.items;

import com.Joy187.newmod.entity.EntityGM79B;
import com.Joy187.newmod.entity.EntityM1897B;
import com.Joy187.newmod.init.ModItems;
import com.Joy187.newmod.util.handlers.SoundsHandler;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Enchantments;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.world.World;

public class ItemM1897 extends ItemBase{
    protected float attackSpeed;

    public ItemM1897(String name,CreativeTabs tab) {
        super(name,tab);
        this.maxStackSize=1;
        this.attackSpeed = -2.2F;

    }
       // 定义按右键可以开火
       public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
        {
            ItemStack itemstack = playerIn.getHeldItem(handIn);
            //开火前会在背包中查看是否有子弹
            boolean flag = !this.findAmmo(playerIn).isEmpty();

            ActionResult ret = net.minecraftforge.event.ForgeEventFactory.onArrowNock(itemstack, worldIn, playerIn, handIn, flag);
            if (ret != null) return ret;

            if (!playerIn.capabilities.isCreativeMode && !flag)
            {
                return flag ? new ActionResult(EnumActionResult.PASS, itemstack) : new ActionResult(EnumActionResult.FAIL, itemstack);
            }
            else
            {
                playerIn.setActiveHand(handIn);
                return new ActionResult(EnumActionResult.SUCCESS, itemstack);
            }   
        }

        //玩家不使用枪械的时候会对背包中的子弹状态进行查看
        public void onPlayerStoppedUsing(ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft)
        {
            if (entityLiving instanceof EntityPlayer)
            {
                EntityPlayer entityplayer = (EntityPlayer)entityLiving;
                boolean flag = entityplayer.capabilities.isCreativeMode || EnchantmentHelper.getEnchantmentLevel(Enchantments.INFINITY, stack) > 0;
                ItemStack itemstack = this.findAmmo(entityplayer);

                int i = this.getMaxItemUseDuration(stack) - timeLeft;
                i = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, worldIn, entityplayer, i, !itemstack.isEmpty() || flag);
                if (i < 0) return;

                if (!itemstack.isEmpty() || flag)
                {
                    if (itemstack.isEmpty())
                    {
                        itemstack = new ItemStack(ModItems.M1897B);
                    }

                    float f = getArrowVelocity(i);

                    if ((double)f >= 0.1D)
                    {
                        boolean flag1 = entityplayer.capabilities.isCreativeMode || (itemstack.getItem() instanceof ItemM1897B && ((ItemM1897B) itemstack.getItem()).isInfinite(itemstack, stack, entityplayer));

                        if (!worldIn.isRemote)
                        {
                            ItemM1897B itemarrow = (ItemM1897B)(itemstack.getItem() instanceof ItemM1897B ? itemstack.getItem() : ModItems.M1897B);
                            //散弹枪,有一发有好多子弹
                            EntityM1897B entity1 = itemarrow.createArrow(worldIn, itemstack, entityplayer);
                            EntityM1897B entity2 = itemarrow.createArrow(worldIn, itemstack, entityplayer);
                            EntityM1897B entity3 = itemarrow.createArrow(worldIn, itemstack, entityplayer);
                            EntityM1897B entity4 = itemarrow.createArrow(worldIn, itemstack, entityplayer);

                            entity1.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F, 1.1F, 0.2F);
                            entity2.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F, 1.0F, 0.6F);
                            entity3.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F, 0.9F, 0.5F);
                            entity4.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F, 1.2F, 0.2F);   

                            if (f == 1.0F)
                            {
                                entity1.setIsCritical(true);
                                entity2.setIsCritical(true);
                                entity3.setIsCritical(true);
                                entity4.setIsCritical(true);                                
                            }

                            int j = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER, stack);

                            if (j > 0)
                            {
                                entity1.setDamage(entity1.getDamage());
                                entity2.setDamage(entity2.getDamage() - (double)j * 0.5D + 0.5D);
                                entity3.setDamage(entity3.getDamage() - (double)j * 0.5D + 0.5D);
                                entity4.setDamage(entity4.getDamage() + 1.5D);

                            }

                            int k = EnchantmentHelper.getEnchantmentLevel(Enchantments.PUNCH, stack);

                            if (EnchantmentHelper.getEnchantmentLevel(Enchantments.FLAME, stack) > 0)
                            {
                                entity1.setFire(100);
                            }

                            stack.damageItem(1, entityplayer);
                            entity1.playSound(SoundsHandler.GM79PRO, 1.5F, 1.5F);

                            worldIn.spawnEntity(entity1);
                            worldIn.spawnEntity(entity2);
                            worldIn.spawnEntity(entity3);
                            worldIn.spawnEntity(entity4);

                        }

                        //开火时播放开火声音文件
                       worldIn.playSound((EntityPlayer)null, entityplayer.posX, entityplayer.posY, entityplayer.posZ, SoundsHandler.GM79PRO, SoundCategory.NEUTRAL, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));

                        if (!flag1 && !entityplayer.capabilities.isCreativeMode)
                        {
                            itemstack.shrink(1);

                            if (itemstack.isEmpty())
                            {
                                entityplayer.inventory.deleteStack(itemstack);
                            }
                        }

                        entityplayer.addStat(StatList.getObjectUseStats(this));
                    }
                }
            }
        }

        //得到子弹初速函数
        public static float getArrowVelocity(int charge)
        {
            float f = (float)charge / 20.0F;
            f = (f * f + f * 2.0F) / 3.0F;

            if (f > 1.0F)
            {
                f = 1.0F;
            }

            return f;
        }

        //查找子弹是否在背包函数
        protected ItemStack findAmmo(EntityPlayer player)
        {
            if (this.isM1897B(player.getHeldItem(EnumHand.OFF_HAND)))
            {
                return player.getHeldItem(EnumHand.OFF_HAND);
            }
            else if (this.isM1897B(player.getHeldItem(EnumHand.MAIN_HAND)))
            {
                return player.getHeldItem(EnumHand.MAIN_HAND);
            }
            else
            {
                for (int i = 0; i < player.inventory.getSizeInventory(); ++i)
                {
                    ItemStack itemstack = player.inventory.getStackInSlot(i);

                    if (this.isM1897B(itemstack))
                    {
                        return itemstack;
                    }
                }

                return ItemStack.EMPTY;
            }
        }

        public int getMaxItemUseDuration(ItemStack stack)
        {
            return 500;
        }

        protected boolean isM1897B(ItemStack stack)
        {
            return stack.getItem() instanceof ItemM1897B;
        }           
}
3.在items包中新建ItemM1897B类(子弹类)

ItemM1897B.java 中编写代码
package com.Joy187.newmod.items;

import com.Joy187.newmod.entity.EntityGM79B;
import com.Joy187.newmod.entity.EntityM1897B;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;

public class ItemM1897B extends ItemBase{

    public ItemM1897B(String name,CreativeTabs tab) {
        super(name,tab);
        //一个格子可以放16发子弹(可以自由修改)
        this.maxStackSize=16;
    }

    //发射时要创造一个子弹实体用于射击
    public EntityM1897B createArrow(World worldIn, ItemStack stack, EntityLivingBase shooter)
    {
        EntityM1897B entity = new EntityM1897B(worldIn, shooter);
        return entity;
    }

    public boolean isInfinite(ItemStack stack, ItemStack bow, net.minecraft.entity.player.EntityPlayer player)
    {
        int enchant = net.minecraft.enchantment.EnchantmentHelper.getEnchantmentLevel(net.minecraft.init.Enchantments.INFINITY, bow);
        return enchant <= 0 ? false : this.getClass() == ItemM1897B.class;
    }
}
4.我们的子弹既是一个物品(Item),同时也是一个实体(Entity),所以我们要新建一个子弹的实体类EntityM1897B


EntityM1897B.java中编写代码
package com.Joy187.newmod.entity;

import java.util.Random;
import java.util.UUID;

import javax.annotation.Nullable;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityWitherSkeleton;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.projectile.EntityFireball;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.entity.projectile.EntityThrowable;
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.RayTraceResult;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;

public class EntityM1897B extends EntitySnowball{
    private static final DataParameter CRITICAL = EntityDataManager.createKey(EntityM1897B.class, DataSerializers.BYTE);

    protected EntityLivingBase thrower;
    private String throwerName;
    public Entity shootingEntity;
    private double damage;  //定义子弹伤害

    public EntityM1897B(World worldIn)
    {
        super(worldIn);
        this.setSize(1.0F, 1.0F);   //设置子弹大小
        this.damage = 8.0D;     //设定子弹伤害
    }

    public EntityM1897B(World worldIn, EntityLivingBase throwerIn)
    {
        super(worldIn, throwerIn);
    }

    public EntityM1897B(World worldIn, double x, double y, double z)
    {
        this(worldIn);
        this.setPosition(x, y, z);
    }   

    //定义子弹撞击物体的函数
    protected void onImpact(RayTraceResult result)
    {
        Random rand = new Random();
        float k = rand.nextFloat();
        if (result.entityHit != null)
        {
            int i = 6;

            //如果子弹打到Zombie或凋零,就增大3点攻击力
            if (result.entityHit instanceof EntityZombie || result.entityHit instanceof EntityWitherSkeleton)
            {
                i = 9;
            }
            result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), (float)i*(1+k));
        }

        //this.world.newExplosion((Entity)null, this.posX, this.posY, this.posZ, (float)this.explosionPower, false, true);

        if (!this.world.isRemote)
        {
            this.world.setEntityState(this, (byte)3);
            this.setDead();
        }
    }

    @Nullable
    public EntityLivingBase getThrower()
    {
        if (this.thrower == null && this.throwerName != null && !this.throwerName.isEmpty())
        {
            this.thrower = this.world.getPlayerEntityByName(this.throwerName);

            if (this.thrower == null && this.world instanceof WorldServer)
            {
                try
                {
                    Entity entity = ((WorldServer)this.world).getEntityFromUuid(UUID.fromString(this.throwerName));

                    if (entity instanceof EntityLivingBase)
                    {
                        this.thrower = (EntityLivingBase)entity;
                    }
                }
                catch (Throwable var2)
                {
                    this.thrower = null;
                }
            }
        }

        return this.thrower;
    }   

    public void setIsCritical(boolean critical)
    {
        byte b0 = ((Byte)this.dataManager.get(CRITICAL)).byteValue();

        if (critical)
        {
            this.dataManager.set(CRITICAL, Byte.valueOf((byte)(b0 | 1)));
        }
        else
        {
            this.dataManager.set(CRITICAL, Byte.valueOf((byte)(b0 & -2)));
        }
    }     

    public double getDamage()
    {
        return this.damage;
    }

    public void setDamage(double damageIn)
    {
        this.damage = damageIn;
    }
}
5.子弹的model.java文件(blockbench文件导出)和render文件同时添加


导出子弹的model.java文件


编写子弹渲染文件,Render1897b.java文件:
package com.Joy187.newmod.entity.render;

import com.Joy187.newmod.entity.EntityAgul;
import com.Joy187.newmod.entity.EntityM1897B;
import com.Joy187.newmod.entity.model.Model1897b;
import com.Joy187.newmod.entity.model.ModelAgul;
import com.Joy187.newmod.util.Reference;

import net.minecraft.util.ResourceLocation;

public class Render1897b {
    public static final ResourceLocation TEXTURES = new ResourceLocation(Reference.Mod_ID + ":textures/entity/m1897b.png");

    protected ResourceLocation getEntityTexture(EntityM1897B entity){

        return TEXTURES;
    }

}
6.导出枪械和子弹的.json文件

将其放入resources的models的item包中

7.在en_us.lang(语言文件)中添加枪械和子弹的物品名称

8.保存所有文件 -> 刷新resources包 -> 运行游戏可以看到我们的枪械和子弹已经成功制作出来了

实战环节:

诶呦不错哦~






[喵喵] 当前离线
积分
73
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-4-6
查看详细资料
发表于 2021-6-16 14:04:10 | 显示全部楼层
终于看见一个关于枪械的教程了
回复

使用道具 举报

[喵喵] 当前离线
积分
73
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-4-6
查看详细资料
发表于 2021-6-16 14:05:12 | 显示全部楼层
感谢大佬的教程
回复

使用道具 举报

peter41463 当前离线
积分
65
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-5-28
查看详细资料
发表于 2021-6-16 22:38:55 | 显示全部楼层
66666666666666
回复

使用道具 举报

雨沫灬 当前离线
积分
265
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2017-6-25
查看详细资料
发表于 2021-6-17 06:53:54 | 显示全部楼层
我终于学会怎么做枪了
回复

使用道具 举报

小六子鸭. 当前离线
积分
794
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2019-8-20
查看详细资料
发表于 2021-6-17 08:11:46 | 显示全部楼层
感谢大佬!!!前些天还正愁怎么实现FPS原理呢!!非常感谢大佬的分享
回复

使用道具 举报

upx1 当前离线
积分
6
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-6-17
查看详细资料
发表于 2021-6-17 09:45:46 | 显示全部楼层
第二种图是内置UI菜单嘛
回复

使用道具 举报

我才是Joy 当前离线
积分
961
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-4-13
查看详细资料
 楼主| 发表于 2021-6-17 12:41:09 | 显示全部楼层
upx1 发表于 2021-6-17 09:45
第二种图是内置UI菜单嘛

第二种 还是 第二张?
回复

使用道具 举报

风叶 当前离线
积分
380
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2019-12-28
查看详细资料
发表于 2021-6-19 21:30:40 | 显示全部楼层
谢谢大佬发来的枪械的教程
回复

使用道具 举报

a997830666 当前离线
积分
157
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-9-28
查看详细资料
发表于 2021-6-20 09:52:13 | 显示全部楼层
我以前在枪械玩过不咋地
回复

使用道具 举报

无涯子- 当前离线
积分
105
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-10-24
查看详细资料
发表于 2021-6-23 10:55:14 | 显示全部楼层
可以 有的参考了 谢
回复

使用道具 举报

冗沉静 当前离线
积分
7
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-2-14
查看详细资料
发表于 2021-7-4 14:39:41 | 显示全部楼层
感觉枪械mod不容易平衡,不管怎么设计便捷性和实用性都要有所取舍。暂时还没有找到好用的mod
回复

使用道具 举报

wdzxk 当前离线
积分
70
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2019-8-6
查看详细资料
发表于 2021-7-4 14:49:39 | 显示全部楼层
教程很详细了,大佬!
回复

使用道具 举报

酒醉的鸵鸟 当前离线
积分
1307
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-11-9
查看详细资料
发表于 2021-8-2 14:16:19 | 显示全部楼层
感觉现在枪械有关的模组已经很多了,不过能做出好的打击感的模组还是很少的。希望lz能在这方面做点努力。
回复

使用道具 举报

贴hghuhb33 当前离线
积分
31
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2021-3-24
查看详细资料
发表于 2021-8-2 15:45:02 | 显示全部楼层
就像维克的现代战争那样的枪械模组
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2021-9-25 08:25 , Processed in 0.079099 second(s), Total 38, Slave 31 queries, Release: Build.2021.09.22 1647, Gzip On, Redis On.

"Minecraft"以及"我的世界"为Mojang Synergies AB的商标 本站与Mojang以及微软公司没有从属关系

© 2010-2020 我的世界中文论坛 版权所有 本站原创图文内容版权属于原创作者,未经许可不得转载

快速回复 返回顶部 返回列表