-
Notifications
You must be signed in to change notification settings - Fork 0
简单网络通信包装类 SimpleNetworkWrapper
在实际开发过程中,我们常常需要用到网络通信。用到网络通信的地方有很多,例如按下按键释放技能,同步玩家属性,监听图形界面按钮按下,让客户端播放特效等等。那么怎么样进行网络通信呢?
为了方便的进行网络通信,Forge提供一个简单的网络通信包装类——SimpleNetworkWrapper
。这个类位于net.minecraftforge.fml.common.network.simpleimpl
包下。
那么,怎么使用这个类呢?首先我们需要获取一个SimpleNetworkWrapper
对象。
NetworkRegistry.INSTANCE.newSimpleChannel(channel);
在此解释一下channel(频道)参数,该参数是一个字符串(String),表示网络通信频道名,只有在相同的频道,数据才能互相传输。
以上代码可以获取到一个SimpleNetworkWrapper
对象,然后我们将这个对象储存至一个静态字段中以便在模组的任何地方调用,比如这样:
@Mod(modid = ChinaCraft.MODID, name = ChinaCraft.NAME, version = ChinaCraft.VERSION)
public final class ChinaCraft {
public static final String MODID = "chinacraft";
public static final String NAME = "ChinaCraft 2";
public static final String VERSION = "0.0.1";
private static SimpleNetworkWrapper network;
@EventHandler
public void init(FMLInitializationEvent event) {
network = NetworkRegistry.INSTANCE.newSimpleChannel(MODID);
}
public static SimpleNetworkWrapper getNetwork() {
return network;
}
}
这样,我们就可以使用ChinaCraft.getNetwork()
方法在模组的任何地方调用SimpleNetworkWrapper
对象了。
接下来,我们开始编写我们的消息类和消息处理类。消息类需要实现IMessage
接口,该类必须要有一个无参构造方法,并且需要实现fromBytes
和toBytes
方法。
public class RedPacketMessage implements IMessage {
public RedPacketMessage() {} //必须要有一个无参构造方法
@Override
public void fromBytes(ByteBuf buf) {} //将字节流转换为信息
@Override
public void toBytes(ByteBuf buf) {} //将信息转换为字节流
}
可以看到,fromBytes
和toBytes
方法都有一个ByteBuf
类型的参数,ByteBuf
类中提供了很多read和write方法,那么我们该如何使用呢?举个例子:
public class RedPacketMessage implements IMessage {
private String sender;
public RedPacketMessage() {}
public RedPacketMessage(String sender) {
this.sender = sender;
}
@Override
public void fromBytes(ByteBuf buf) {
char chars[] = new char[buf.readInt()]; //读取字符串长度
for(int i=0;i<chars.length;i++) //读取字符
chars[i] = buf.readChar();
sender = String.valueOf(chars); //创建字符串对象
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeInt(sender.length()); //写入字符串长度
for(char c:sender.toCharArray()) //写入字符串
buf.writeChar(c);
}
提示:可以看到
ByteBuf
类有些不方便使用,所以可以使用MC实现的PacketBuffer
类和Forge提供的ByteBufUtils
类。
接下来,我们需要为这个消息编写一个处理类,来处理收到的消息,消息处理类需要实现IMessageHandler
接口,并且需要实现onMessage
方法。此外,该接口还是一个泛型接口,拥有两个泛型形参REQ extends IMessage
和REPLY extends IMessage
,其中REQ表示收到的消息类,REPLY表示回复的消息类。
public class RedPacketMessageHandler implements IMessageHandler<RedPacketMessage, IMessage> {
@Override
public IMessage onMessage(RedPacketMessage message, MessageContext ctx) {
return null; //当你不需要回复消息时,可以将REPLY填写为IMessage,并且返回null;
}
}
接下来,我们需要将消息类和消息处理类注册到SimpleNetworkWrapper
对象中。
network.registerMessage(handler,message,id,side);
解释一下registerMessage
方法的四个参数,第一个参数handler需要一个IMessageHandler
对象,第二个参数message则是对应的消息类的类对象,第三个参数id表示该消息的id,范围为0~255,且不得重复,第四个参数side表示收到消息的对象,Side.SERVER
表示消息由客户端发送,服务器接收,Side.CLIENT
表示消息由服务端发送,客户端接收。
那么,注册好了以后我们怎么发送消息呢?SimpleNetworkWrapper
类实现了五个发送方法,分别有不同的作用。
/**
* 发送消息给所有玩家(服务端调用该方法)
*/
public void sendToAll(IMessage message)
/**
* 发送消息到指定玩家(服务端调用该方法)
*/
public void sendTo(IMessage message, EntityPlayerMP player)
/**
* 发送消息到指定范围内的所有玩家(服务端调用该方法)
*/
public void sendToAllAround(IMessage message, NetworkRegistry.TargetPoint point)
/**
* 发送消息到指定世界内的所有玩家(服务端调用该方法)
*/
public void sendToDimension(IMessage message, int dimensionId)
/**
* 发送消息到服务器(客户端调用该方法)
*/
public void sendToServer(IMessage message)
例如:
ChinaCraft.getNetwork().sendToServer(new RedPacketMessage());
public class RedPacketMessage implements IMessage {
private String sender;
public RedPacketMessage() {}
public RedPacketMessage(String sender) {
this.sender = sender;
}
@Override
public void fromBytes(ByteBuf buf) {
sender = ByteBufUtils.readUTF8String(buf);
}
@Override
public void toBytes(ByteBuf buf) {
ByteBufUtils.writeUTF8String(buf,sender);
}
本篇教程到这就结束了,感谢您的阅读。