Minecraft 1.12.2模组开发(四十二) 按键效果(KeyBinding)

你是否想在MC中实现一个效果,当你按下一个键的时候就会触发一个特殊效果(召唤、获得一个buff、传送到一个地点),我们今天就着手实现MC中的键位控制。

cr.jpg

1.Java包中新建一个keys包 -> keys包中新建ModKeyBinding类

ModKeyBinding.java

package com.joy187.rejoymod.keys;

import com.joy187.rejoymod.IdlFramework;
import com.joy187.rejoymod.proxy.ClientProxy;
import net.minecraft.client.settings.KeyBinding;
import net.minecraftforge.client.settings.IKeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier;

//@SideOnly(Side.CLIENT)
public class ModKeyBinding extends KeyBinding {
    public ModKeyBinding(String description, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, int keyCode, String category) {
        super(String.format("key.%s.%s", IdlFramework.MODID, description), keyConflictContext, keyModifier, keyCode, category);
        //将模组中所有键位进行注册
        ClientProxy.KEY_BINDINGS.add(this);
    }

}

2.找到我们的ClientProxy类,添加模组所有键位的信息:

ClientProxy.java

package com.joy187.rejoymod.proxy;

import com.joy187.rejoymod.init.ModParticles;
import com.joy187.rejoymod.keys.ModKeyBinding;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.Item;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.settings.KeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier;
import org.lwjgl.input.Keyboard;

import java.util.ArrayList;
import java.util.List;

public class ClientProxy extends ProxyBase {
    public static final List<KeyBinding> KEY_BINDINGS = new ArrayList<KeyBinding>();
    
    //我们所有的键位进行声明  参数最重要的是Keyboard.KEY_X 对应我们的按键,其他基本不变
	public static final KeyBinding SUMMON = new ModKeyBinding("activate_skill_summon", KeyConflictContext.IN_GAME, KeyModifier.NONE, Keyboard.KEY_V, "key.category.rejoymod");
	public static final KeyBinding EFFECTME = new ModKeyBinding("activate_skill_effectme", KeyConflictContext.IN_GAME, KeyModifier.NONE, Keyboard.KEY_R, "key.category.rejoymod");

	public boolean isServer()
	{
		return false;
	}

	public void registerItemRenderer(Item item, int meta, String id)
	{
		ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(item.getRegistryName(), id));
	}

	@Override
	public void registerParticles() {
		ModParticles.registerParticles();
	}
}

3.在keys包中新建KeyboardManager类用于管理键位事件(按下相应键后会发生什么):

我们想让自己按下R键后有个随机传送的效果:

KeyboardManager.java

package com.joy187.rejoymod.keys;

import com.joy187.rejoymod.IdlFramework;
import com.joy187.rejoymod.item.ModItems;
import com.joy187.rejoymod.item.skills.ItemSkillBase;
import com.joy187.rejoymod.network.NetworkHandler;
import com.joy187.rejoymod.network.protocols.PacketTest;
import com.joy187.rejoymod.proxy.ClientProxy;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.util.Random;

//@SideOnly(Side.CLIENT)
@Mod.EventBusSubscriber
public class KeyboardManager {
    //ref: https://harbinger.covertdragon.team/chapter-18/keyboard.html

    public static void init() {
        for (KeyBinding key:
             ClientProxy.KEY_BINDINGS) {
            ClientRegistry.registerKeyBinding(key);
        }
        IdlFramework.Log("Registered %d keys", ClientProxy.KEY_BINDINGS.size());
    }

    @SideOnly(Side.CLIENT)
    @SubscribeEvent
    public static void onKeyPressed(InputEvent.KeyInputEvent event) {
        //当按下EFFECTME键(V键)时
        if (ClientProxy.EFFECTME.isPressed()) {

            Minecraft mc = Minecraft.getMinecraft();
            EntityPlayerSP player = mc.player;
            if(player == null) return;
            if(mc.isGamePaused()) return;
            if(!mc.inGameHasFocus) return;
            if(mc.currentScreen != null) return;

            EnumHand hand = ClientProxy.EFFECTME.isKeyDown() ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND;
            IdlFramework.Log("pressed key cast :" + hand);
            Random ran = new Random();
            //玩家以20为半径随机传送
            player.setPosition(player.getPositionVector().x+ran.nextInt(20),player.getPositionVector().y,player.getPositionVector().z+ran.nextInt(20));
            //mc.playerController.updateController();
            //                    NetworkManager.channel.sendToServer(new C2SSpecialAction((byte) 1));
        }
    }
}
药水效果可以使用addPotionEffect函数实现:
//给予5s凋零效果
palyer.addPotionEffect(new PotionEffect(MobEffects.WITHER, 20*5));
找到我们的Main类,在init函数中添加KeyboardManager的初始化信息:
    @EventHandler
    public static void Init(FMLInitializationEvent event) {

        //添加键位初始化信息,我们的按键效果只在客户端生效
        if (!proxy.isServer())
        {
            KeyboardManager.init();
        }


	}

cr1.jpg

4.当穿上盔甲后按下键实现召唤生物的效果,我们可以找到自己的盔甲类,以ArmorMirandaSuit为例:

我们要找到一个函数onArmorTick,它有检测我们是否穿上了盔甲的作用

package com.joy187.rejoymod.item.armor;

import com.joy187.rejoymod.IdlFramework;
import com.joy187.rejoymod.entity.EntityEthan;
import com.joy187.rejoymod.entity.EntityGaia;
import com.joy187.rejoymod.entity.EntityM1851B;
import com.joy187.rejoymod.entity.ModEntityInit;
import com.joy187.rejoymod.entity.projectiles.ProjectileArgs;
import com.joy187.rejoymod.item.ModItems;
import com.joy187.rejoymod.proxy.ClientProxy;
import com.joy187.rejoymod.util.IHasModel;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityEvoker;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityEvokerFangs;
import net.minecraft.entity.projectile.EntityWitherSkull;
import net.minecraft.init.MobEffects;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemMonsterPlacer;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

public class ArmorMirandaSuit extends ItemArmor implements IHasModel {
    public ArmorMirandaSuit(String name, CreativeTabs tab, ItemArmor.ArmorMaterial materialIn, EntityEquipmentSlot equipmentSlotIn) {
        super(materialIn, 1, equipmentSlotIn);
        setUnlocalizedName(name);
        setRegistryName(name);
        setCreativeTab(tab);
        setMaxStackSize(1);
        ModItems.ITEMS.add(this) ;
    }

    @Override
    public void registerModels() {
        IdlFramework.proxy.registerItemRenderer(this, 0, "inventory");
    }

    @Override
    public ModelBiped getArmorModel(EntityLivingBase entity, ItemStack itemStack, EntityEquipmentSlot armorSlot, ModelBiped _default) {
        if(!itemStack.isEmpty())
        {
            if(itemStack.getItem() instanceof ItemArmor)
            {
                MirandaSuit model = new MirandaSuit();

                model.bone.showModel = armorSlot == armorSlot.CHEST;
//                model.LeftArm.showModel = armorSlot == armorSlot.CHEST;
//                model.RightArm.showModel = armorSlot == armorSlot.CHEST;

                model.leftArmPose = _default.leftArmPose;
                model.rightArmPose = _default.rightArmPose;
                model.isChild = _default.isChild;
                model.isRiding= _default.isRiding;
                model.isSneak = _default.isSneak;


                return model;
            }
        }
        return null;
        //.applyEntityStats(defaultArmor).applySlot(EquipmentSlotType.HEAD);
    }

    @Override
    public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack){
        if(player.inventory.armorItemInSlot(2).getItem() == ModItems.MIRANDASUIT &&
                player.inventory.armorItemInSlot(2)!=null) {
            //如果要穿上好几件才能触发按键效果的话,你可以把这些都加入到上面的if判断中
            //护腿:player.inventory.armorItemInSlot(1).getItem() == ModItems.FRANK_LEG && player.inventory.armorItemInSlot(1)!=null      
            //头盔:player.inventory.armorItemInSlot(3).getItem() == ModItems.FRANK_HEAD && player.inventory.armorItemInSlot(3)!=null
            //靴子:player.inventory.armorItemInSlot(0).getItem() == ModItems.FRANK_BOOTS && player.inventory.armorItemInSlot(0)!=null
            
            effectPlayer(player, MobEffects.HASTE, 0, 3);
            effectPlayer(player, MobEffects.REGENERATION, 0, 3);
            //此时当我们按下SUMMON键(R键),就会生成一个凋零骷髅头
            if(ClientProxy.SUMMON.isPressed())
            {
                
                world.playEvent((EntityPlayer)null, 1024, new BlockPos(player), 0);
                double d0 = player.getLookVec().x;
                double d1 = player.getLookVec().y;
                double d2 = player.getLookVec().z;
                double d3 = player.posX-d0;
                double d4 = player.posY-d1;
                double d5 = player.posZ-d2;
                EntityWitherSkull e = new EntityWitherSkull(world, player, d0, d1, d2);
                //主世界生成骷髅头
                player.world.spawnEntity(e);
            }
        }
        super.onArmorTick(world, player, itemStack);

    }

    private void effectPlayer(EntityPlayer player, Potion effect, int duration, int amplifier) {
        if(player.getActivePotionEffect(effect)==null || player.getActivePotionEffect(effect).getDuration() <=1) {
            player.addPotionEffect(new PotionEffect(effect, duration,  amplifier, false, true));
        }
    }

}

5.保存所有文件 -> 进入游戏调试

没有穿上胸甲,按下R键,没有反应

2022-04-13_15.50.07.png

穿上后按下R键,我们发现凋零骷髅头成功发射!

cr13.jpg

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay_fearless

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

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

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

打赏作者

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

抵扣说明:

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

余额充值