Monday, July 14, 2014

Minecraft Forge 1.7 - Setting up Networking Components (newEventDrivenChannel)

After core Minecraft changed to using Netty for its network operations, Forge's network model changed considerably. They did a great job changing it, but the full road to getting packet dispatching working is documented literally nowhere. The wiki tutorials that claim to be the new way all have a message from the Forge team telling people that they are wrong.

I think I've done a decent job figuring out what needs to happen, so I'll document it here. Yay, internet learning!

First, you'll need to register a packet channel. Unlike in the pre-1.7 days when you had to register a bunch of different channels for each packet type, we will differentiate them with a map of integers to packet subclasses. Declare an FMLEventChannel variable in your mod class, preferably static:

public static FMLEventChannel NetworkCon;

Then, in your mod's handler for FMLServerStartingEvent, register the channel and assign it to that variable, like this:

@EventHandler
public void serverLoad(FMLServerStartingEvent event) {
FMLEventChannel net = NetworkRegistry.INSTANCE.newEventDrivenChannel(MODID);
NetworkCon = net;
}

(Replace MODID with your mod's ID name or use a constant you defined already.) Now, create a class to hold event handlers related to networking, I'll call mine NetworkHandler.

public class NetworkHandler {
@SubscribeEvent
public void onServerPacket(ServerCustomPacketEvent e) {

}
@SubscribeEvent
public void onClientPacket(ClientCustomPacketEvent e) {

}
}


Register that class as a receiver for the channel. If you get an error on the registration later, annotate the NetworkHandler class with @Sharable. Place this in the handler for FMLServerStartingEvent:

net.register(new NetworkHandler());

It's now up to you to register your packet types, which will be in another article - or you could create your own implementation! You can send them with the obviously named methods in the channel object and handle them in the packet event handlers. On the server, you can get the player by casting e.handler to NetHandlerPlayServer and accessing playerEntity, which is not obvious at all. I have this little utility method:

private EntityPlayerMP getSendingPlayer(ServerCustomPacketEvent e) {
return ((NetHandlerPlayServer)e.handler).playerEntity;
}

Happy modding!

No comments:

Post a Comment