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

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

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

cr.png

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

cr1.png

2.在ModItems中添加我们刚刚制作的两个物品的信息

	public static final Item W870 = new ItemM1897("w870", Main.ITEM_TAB);
	public static final Item M1897B = new ItemM1897B("m1897b", Main.ITEM_TAB);

cr2.png

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

cr3.png

在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<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
	    {
	        ItemStack itemstack = playerIn.getHeldItem(handIn);
	        //开火前会在背包中查看是否有子弹
	        boolean flag = !this.findAmmo(playerIn).isEmpty();

	        ActionResult<ItemStack> 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<ItemStack>(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<Byte> CRITICAL = EntityDataManager.<Byte>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文件

cr4.png

编写子弹渲染文件,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文件

cr5.png

将其放入resources的models的item包中

cr6.png

7.在en_us中添加枪械和子弹的物品名称

cr7.png

8.保存所有文件 -> 刷新resources包 -> 运行游戏

可以看到我们的枪械和子弹已经成功制作出来了

2021-06-15_18.07.17.png

实战环节:

2021-06-15_18.05.56.png

诶呦不错哦~

2021-06-15_18.04.52.png

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay_fearless

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

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

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

打赏作者

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

抵扣说明:

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

余额充值