我们今天在世界中创造一把属于自己的霰弹枪
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<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文件
编写子弹渲染文件,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中添加枪械和子弹的物品名称
8.保存所有文件 -> 刷新resources包 -> 运行游戏
可以看到我们的枪械和子弹已经成功制作出来了
实战环节:
好家伙