本篇教程参考为的NeoForge1.20.4Mod开发的视频,这篇教程是我边学边总结的,与其说是教程更像我的学习笔记,如有不清楚的地方,大家可以在评论区提问。在我力所能及的范围内,我都会解答的。
首先我们讲一下发包的过程,具体过程如下:
通过本地、局域网传输或者因特网传输
构建数据包=>序列化成字节流 ===============================> 反序列化成实例 => 实现操作
定义数据包
public record MyData(String message, int age) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(ExampleMod.MODID, "mydata");
public MyData(final FriendlyByteBuf buf) {
this(buf.readUtf(), buf.readInt());//反序列化
}
@Override
public void write(FriendlyByteBuf buffer) {//序列化
buffer.writeUtf(message());
buffer.writeInt(age());
}
@Override
public ResourceLocation id() {
return ID;
}
}
S2C
这种情况是服务端发包,客户端接受并处理数据包
public class ClientPayloadHandler {
private static final Logger LOGGER = LogManager.getLogger();//打印信息用,非必要
private static final ClientPayloadHandler INSTANCE = new ClientPayloadHandler();
public static ClientPayloadHandler getInstance() {
return INSTANCE;
}
public void handleData(final MyData data, final PlayPayloadContext context) {
//在network线程中对数据进行处理的话,代码写在这里
context.workHandler().submitAsync(()->{
//在Main线程里面做一些的操作的话,代码写在这里
LOGGER.info(data.message());
}).exceptionally(e -> {
context.packetHandler().disconnect(Component.translatable("my_mod.network_disconnect",e.getMessage()));
return null;
});
}
}
handleData是我们处理数据包的方法,第一个参数就是对应数据包的类型,第二个参数是网路的上下文,包含了网络的发包人和其他信息
C2S
这种情况是客户端发包,服务端接受并处理数据包
public class ServerPayloadHandler {
private static final Logger LOGGER = LogManager.getLogger();
private static final ServerPayloadHandler INSTANCE = new ServerPayloadHandler();
public static ServerPayloadHandler getInstance() {
return INSTANCE;
}
public void handleData(final MyData data, final PlayPayloadContext context) {
context.workHandler().submitAsync(()->{
LOGGER.info(data.message());
}).exceptionally(e -> {
context.packetHandler().disconnect(Component.translatable("my_mod.network_disconnect",e.getMessage()));
return null;
});
}
}
网路注册
@Mod.EventBusSubscriber(modid = ExampleMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Networking {
@SubscribeEvent
public static void register(final RegisterPayloadHandlerEvent event) {
final IPayloadRegistrar payloadRegistrar = event.registrar(ExampleMod.MODID);
payloadRegistrar.play(MyData.ID,MyData::new,handler ->
handler.client(ClientPayloadHandler.getInstance()::handleData)
.server(ServerPayloadHandler.getInstance()::handleData));
}
}
在MOD总线里监听RegisterPayloadHandlerEvent,把MyData这个payload绑定到客户端/服务端处理器
payload就是“包里真正携带的数据内容”。
MyData就是payload:
message、age 是数据本体
write(…) / 构造器 MyData(FriendlyByteBuf) 负责序列化和反序列化
id()(examplemod:mydata)告诉网络层“这是什么类型的payload”
网络层负责“送快递”,payload 是“快递盒子里的东西”
触发
public class MessageItem extends Item {
public MessageItem() {
super(new Properties());
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (world.isClientSide) {
PacketDistributor.SERVER.noArg().send(new MyData("From client",2));
}
if (!world.isClientSide) {
PacketDistributor.PLAYER.with((ServerPlayer) player).send(new MyData("From server",2));
}
return super.use(world,player,hand);
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END









暂无评论内容