Forge Mod Loader or FML has multiple ways for handling packets, some are not recommended such as this and if you can load that page (Sometimes the MinecraftForge wiki is down) CPW has kindly left a large notice saying that that method WILL result in a memory leak. CPW there also suggested that we use the SimpleNetworkWrapper that has been out for a while.
What is it?
FML’s SimpleNetworkWrapper is a basic method of creating a message based system though it does have it’s downsides such as not being able to have a common packet handler and therefore needing a packet handler for each message to be sent.
Creating the Channel
To create a channel that your mod uses for the communication between your mod on the clients and the server you use the following snippet where SimpleNetworkWrapper is located at
Writing the Message
Writing a message for Netty is a relatively painless process that can be assisted in terms of IDE templates but you should understand what it is.
Each message has to implement
cpw.mods.fml.common.network.simpleimpl.IMessage so that the SimpleNetworkWrapper can know how to encode and decode your message.
There is also the secondary requirement for all messages, an
IMessageHandler<REQ, REPLY> which is recommended to either have as an entirely separate class, or as an inner class of the
IMessage to keep the code within the same place.
An example message can be shown as follows.
As you can see, this is only a boilerplate class and effectively does nothing on sending and receiving the packet but can be easily expanded by adding parameters and the functionality to the
For this example we will make this
IMessage send a random integer to the server and then reply back to the client with what the integer was.
So, for this example we will obviously need a field of what our random integer was and a method to generate it which we will be doing in the constructor using java.util.Random and stored in a variable called
So, we end up changing a small part of the class to be:
This does the generation of the value that we will send to the server, but this is not enough to send this packet to the server and then have it work, since we have not wrote and read it from the bytes sent to the server.
To do this, we need to add some functionality to the
toBytes(ByteBuf) functions in our SampleMessage.
Now that we have that done this, when we send the packet to the server it will know what we said the random number would be. All we now have to do is handle the packet and register it.
Handling the packet
In the example in the above we use the Handler inner class to handle that specific message so what we will be doing is using it to add a new
ChatComponentText to the player’s chat so they can see the response (In 1.7.2 you do not need the ChatComponentText, just a string).
Notice how, in the handler, we use message.value but not value in reference to the parent class? this is because the message is not handled in the same instance of the Handler as it was decoded, so it is recommended to make it a inner class so you avoid using the wrong parameter.
Right about now, we are returning null for the
onMessage function, and what the return value for that is a reply message to send back to the client when received.
Registration and Sending
To be able to send this Message we need to register the message back with the SimpleNetworkWrapper we created in Creating the Channel by using the function
To explain the values of
registerMessage it is firstly the class of the handler for the message, then the class of the message itself, a discriminator (make it unique for all messages) and then the side the packet gets sent to.
Sending the message is as just as easy as running the sendToServer function on the client.