Minecraft 1.12.2模组开发(五十六) 网络(Networking)

我们本次在模组中实现客户端向服务器发送数据的功能。


演示效果 演示效果 演示效果

1.新建packet包,包中新建PacketHandler类:

PacketHandler.java

package com.joy187.mcjoygun.packet;

import com.joy187.mcjoygun.Main;
import com.joy187.mcjoygun.utils.SerializableUtil;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLEventChannel;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;

public class PacketHandler {
//    public static final String[] CHANNELS = {"testmsg", "levelupclasses"};
//    public static FMLEventChannel initChannel,otherChannel;

    public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(Main.MODID);
    static int id = 0;

    public static void init() {
        PacketHandler handler = new PacketHandler();
        //注册该数据包类
        INSTANCE.registerMessage(MessageRangeAttackHandler.class, MessageRangeAttack.class, id++, Side.SERVER);

        MinecraftForge.EVENT_BUS.register(handler);
    }

}

在项目主类Main中的preInit类中添加PacketHandler的初始化函数:

Main.java

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        PacketHandler.init();
        //RegistryHandler.preInitRegistries(event);
    }

2.packet包中新建一个MessageRangeAttack类:

MessageRangeAttack.java


package com.joy187.mcjoygun.packet;

import com.google.common.collect.Maps;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;

import java.util.Map;

public class MessageRangeAttack implements IMessage {

    public RangeAttackState mode;
    //定义几个可以枚举的攻击状态,之后会用到
    public enum RangeAttackState{UPKEY(1),
        BLISTERING(2),
        STORM(3);

        private final byte data;


        public static RangeAttackState getState(byte data){
            return stateMap.get(data);
        }
        private static final Map<Byte,RangeAttackState> stateMap = Maps.newHashMap();

        static {
            for (RangeAttackState value : values())
            {
                stateMap.put(value.data, value);
            }
        }

        RangeAttackState(int value){
            data = (byte)value;
        }

        public byte getData() {
            return data;
        }
    }

    public MessageRangeAttack(){};

    public MessageRangeAttack(RangeAttackState mode){
        this.mode = mode;
    }

    @Override
    public void fromBytes(ByteBuf buf) {
        this.mode = RangeAttackState.getState(buf.readByte());
    }

    @Override
    public void toBytes(ByteBuf buf) {
        buf.writeByte(this.mode.getData());
    }
}

同时新建一个MessageRangeAttackHandler类,作为上面那个类的管理器:

MessageRangeAttackHandler.java

package com.joy187.mcjoygun.packet;


import com.joy187.mcjoygun.items.ToolXuanFeng;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;


public class MessageRangeAttackHandler implements IMessageHandler<MessageRangeAttack,IMessage> {

    @Override
    public IMessage onMessage(MessageRangeAttack message, MessageContext ctx) {

        if(ctx.getServerHandler() == null) return null;
        EntityPlayerMP entityPlayer = ctx.getServerHandler().player;
        if(entityPlayer == null) return null;
        
        entityPlayer.getServerWorld().addScheduledTask(() -> {
            ItemStack stack = entityPlayer.getHeldItem(EnumHand.MAIN_HAND);
            //检查玩家手上是否拿着特定的武器,如果持有该武器就可以向服务器发送数据包
            if (!stack.isEmpty() && stack.getItem() instanceof ToolXuanFeng) {
                //输出yes
                System.out.println("yes");
                ((ToolXuanFeng) stack.getItem()).doRangeAttack(stack, entityPlayer, message.mode);
            }
        });

        return null;
    }
}

3.我们在KeyboardManager中给这个武器绑定两个键位事件:

KeyboardManager.java

@Mod.EventBusSubscriber
public class KeyboardManager {

    public static void init() {
        for (KeyBinding key:
             ClientProxy.KEY_BINDINGS) {
            ClientRegistry.registerKeyBinding(key);
        }
    }

    @SideOnly(Side.CLIENT)
    @SubscribeEvent
    public static void onKeyPressed(InputEvent.KeyInputEvent event) {
        
        //按键1按下就向服务器发送一个包,攻击状态为UPKEY
        if (ClientProxy.KEY1.isPressed()) {

            PacketHandler.INSTANCE.sendToServer(new MessageRangeAttack(MessageRangeAttack.RangeAttackState.UPKEY));
        }
        
        //按键2按下就向服务器发送一个包,攻击状态为STORM
        if(ClientProxy.KEY2.isPressed()){
            PacketHandler.INSTANCE.sendToServer(new MessageRangeAttack(MessageRangeAttack.RangeAttackState.STORM));
        }
    }
}

在项目主类中添加键位管理的初始化函数:

Main.java

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        MinecraftForge.EVENT_BUS.register(this);
        FMLCommonHandler.instance().bus().register(this);
        //添加键位管理的注册函数
        if (!proxy.isServer())
        {
            KeyboardManager.init();
        }
    }

4.准备一个武器类ToolXuanFeng,对范围攻击状态进行定义:

ToolXuanFeng.java

package com.joy187.mcjoygun.items;

import com.joy187.mcjoygun.Main;
import com.joy187.mcjoygun.init.ItemInit;
import com.joy187.mcjoygun.packet.MessageRangeAttack;
import com.joy187.mcjoygun.packet.PacketHandler;
import com.joy187.mcjoygun.utils.IhasModel;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Enchantments;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemAxe;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.util.SoundCategory;
import net.minecraft.world.World;

import java.util.EnumSet;

public class ToolXuanFeng extends ItemAxe implements IhasModel {
    public ToolXuanFeng(String name, CreativeTabs tab, ToolMaterial material) {
        super(material,34.0F,-3.3F);
        setUnlocalizedName(name);
        setRegistryName(name);
        setCreativeTab(tab);

        ItemInit.ITEMS.add(this);
    }

    //该武器的范围攻击函数
    public void doRangeAttack(ItemStack item, EntityLivingBase entity, MessageRangeAttack.RangeAttackState mode) {
        //函数被调用时输出okokok
        System.out.println("okokok");
        switch(mode) {
            //当攻击状态为UPKEY时,就释放大爆炸
            case UPKEY: {
                entity.world.createExplosion(entity, entity.posX, entity.posY, entity.posZ, (float) (4.0D + entity.getRNG().nextDouble() * 1.5D * 1), true);
                break;
            }
            //当攻击状态为STORM时,就产生雷鸣
            case STORM:{
                entity.world.addWeatherEffect(new EntityLightningBolt(entity.world, entity.posX, entity.posY, entity.posZ, true));
                //entity.world.setLastLightningBolt(2);
                break;
            }
        }

    }

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

在ItemInit中注册该武器:

ItemInit.java

    public static final ItemAxe FENBAOCHUI = new ToolXuanFeng("xuanfengaxe", Main.ITEM_TAB, MATERIAL_XUANFENG);

5.保存代码 -> 进行调试。

你可以在控制台查看数据包是否发送:Minecraft 1.12.2模组开发(五十六) 网络(Networking)_第1张图片

你可能感兴趣的:(我的世界,网络,java,jvm)