Anything that changes the world state should ALWAYS be done on the server. If you cannot run your code directly on the server side for some reason, then you need to send a packet. Commands, however, are already server side.
I am having to use the ray trace method, which is client side, and collect the BlockPos of where I'm going to place a block. I found the method, world.rayTraceBlocks(Vec, Vec1, false, false, true), but in order to collect the Vec variables, I need to call a method that is client side only.
EDIT: I made a packet class called Place Block and it is registered. And sorry, I didn't mean command. I got it mixed up
public class PlaceBlock extends AbstractServerMessage<PlaceBlock>
{
private BlockPos pos;
private int x, y, z;
private IBlockState block;
// The basic, no-argument constructor MUST be included to use the new automated handling
public PlaceBlock() {}
// if there are any class fields, be sure to provide a constructor that allows
// for them to be initialized, and use that constructor when sending the packet
public PlaceBlock(int x, int y, int z, IBlockState teraBlock) {
this.pos = new BlockPos(x, y, z);
this.block = teraBlock;
}
@Override
protected void read(PacketBuffer buffer) {
// basic Input/Output operations, very much like DataInputStream
pos = buffer.readBlockPos();
}
@Override
protected void write(PacketBuffer buffer) {
// basic Input/Output operations, very much like DataOutputStream
buffer.writeBlockPos(pos);
}
@Override
public void process(EntityPlayer player, Side side) {
// using the message instance gives access to 'this.id'
player.worldObj.setBlockState(pos, block);
}
And the method that calls it.
//when Right clicked
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
When ran, the game crashes when I right click with the item. I debugged for a while and am not sure why.
I don't mean to make you baby me through this, and by no means do you have to, but I am one of those guys that won't understand how this works until suddenly, for some reason, It clicks and I understand.
onItemUse already has the position and side of the block clicked, so why are you doing all this extra work yourself? If you are trying to place a block very far away, you can still determine the block hit on the server side by copying much of the RayTrace code to make a non-client-only version (there isn't anything really special about it that it needs to be client only, it's mainly just an artifact of decompilation).
As for your error, ALWAYS post a crash report. Makes it way easier to debug.
Your problem is very likely a NullPointerException, because you have to consider that the player may not actually be looking at anything. So if the player is looking up at the sky and right clicks, what do you expect the BlockPos to be? Certainly not a valid block, I'll tell you that much.
I don't know much about java, but I'd like to learn, and am slowly figuring this crap out.
Until I know what I need to know though, I'm a little lost, and could use some help/direction.
So Itoss, the guy who made magiccrusade, told me that to prevent his class selection from popping up on first login, I needed to "Try to send the packet serverside whenever you want, and not when the player login" ... Now I'm happy he responded but I have no fkn clue what he means. I tried searching the sourcecode to find what I needed but I gotta be honest, only certain sections of source make any sense to me right now.
Could someone help me out? I'm not asking for you to straight do it for me, I mean that would be nice, but I understand that you can't help someone who wont help themselves.
I don't know much about java, but I'd like to learn, and am slowly figuring this crap out.
Until I know what I need to know though, I'm a little lost, and could use some help/direction.
So Itoss, the guy who made magiccrusade, told me that to prevent his class selection from popping up on first login, I needed to "Try to send the packet serverside whenever you want, and not when the player login" ... Now I'm happy he responded but I have no fkn clue what he means. I tried searching the sourcecode to find what I needed but I gotta be honest, only certain sections of source make any sense to me right now.
Could someone help me out? I'm not asking for you to straight do it for me, I mean that would be nice, but I understand that you can't help someone who wont help themselves.
Any help appreciated
Sorry, I have no idea what he's talking about either. I'm not familiar with that mod, and I'm not really sure what you are doing - are you making another mod that interacts with his mod, or just trying to stop his mod from doing something?
Anyway, it sounds like an issue you need to discuss with the mod maker, or make a general help request in the Modification Development section, as it is not related to this tutorial.
On the syncPlayerProps message part of the tutorial. How would I configure that to sync WorldData? Such as a class that extends WorldSavedData.
Thanks again for the tutorial. It's gotten me pretty far into my mod.
You wouldn't. WorldData is completely separate from IEEP. What are you trying to accomplish, i.e. what, exactly, are you storing in WorldData that you need the client player to know about?
You answered my question! I wasn't sure if I was suppose to use packets for it. Now I'm stuck with WorldSavedData not saving. I'll start another thread. Thanks
Rollback Post to RevisionRollBack
I complicate easy problems, come begging for help, and leave with a simple solution.
Hey there again! I'm having an issue that you may be able to shed some light on.. Hopefully.
So I have an IExtendedEntity class that is edited on the client side. In order for it to update on the server side, would I send the packet to the server?
If so... well, for some reason it isn't being updated on the server side, even when I do dispatch a packet...
Basically, the player stores an IBlockState id. This id is changed when the player is crouching and he presses f, but this can only be done client side.
Here is my packet Dispatcher class. It's the class named 'SyncCurrentMimicBlockState'. It is being registered as Side.CLIENT as well. http://pastebin.com/Ydv74KaB
You need to register the packet to the side that will RECEIVE it, not the side that will send it, so it should be Side.SERVER.
What I would do instead of sending all of that data is to send a packet directly from the key press, saying "player A pressed key X", or even "player A is requesting to do action X", then have the server perform the logic that you currently do in your KeyInputEvent. The client should only ever send requests to the server to perform an action and determine the result - it should never be telling the server what the result is directly.
You should use Keyboard.getEventKey() to find the key code of the key pressed, as YourKeyBinding.isPressed() may return true even if it is not the key causing the input event (e.g. the player is holding it down while pressing other keys).
What I would do instead of sending all of that data is to send a packet directly from the key press, saying "player A pressed key X", or even "player A is requesting to do action X", then have the server perform the logic that you currently do in your KeyInputEvent.
In what case would I use syncCurrentMimicBlockState?
How would I tell the server side to perform such an action?
You should use Keyboard.getEventKey() to find the key code of the key pressed, as YourKeyBinding.isPressed() may return true even if it is not the key causing the input event (e.g. the player is holding it down while pressing other keys).
In what case would I use syncCurrentMimicBlockState?
How would I tell the server side to perform such an action?
You should NEVER have a packet like yours that syncs data from client -> server, only the other way around. You only need to sync from server -> client if the client needs to know about it, e.g. for a GUI.
To have the server perform an action, you send a packet:
1. Player clicks button
2. Packet gets sent: "Player A clicked button X"
3. Server receives packet and does whatever needs to be done for button X
You can do anything you want when processing a packet, not just set variables.
To have the server perform an action, you send a packet:
1. Player clicks button
2. Packet gets sent: "Player A clicked button X"
3. Server receives packet and does whatever needs to be done for button X
Is the packet the class that I pass? IE. The SyncCurrentMimicBlockState.class
would I create a different class that holds variables, set those variables, then send that in a packet like I did with SyncCurrentMimicBlockState? (PacketDispatcher.sendToServer(new DoStuff.class))
Rollback Post to RevisionRollBack
I complicate easy problems, come begging for help, and leave with a simple solution.
Is the packet the class that I pass? IE. The SyncCurrentMimicBlockState.class
would I create a different class that holds variables, set those variables, then send that in a packet like I did with SyncCurrentMimicBlockState? (PacketDispatcher.sendToServer(new DoStuff.class))
You should research how packets work - it's not a concept unique to Minecraft.
A class, whether it's a 'Packet' or any other class, is just a way to encapsulate information and behavior, but the class definition itself is just that - a definition.
So yes, you would create a new packet class that, within its definition, defines any data (class fields, i.e. variables) that you need to pass to the server (probably none, in your particular case) and then also define some behavior (i.e. methods) that are called when the packet gets processed - that's where things actually happen, and in the case of Minecraft / Forge, those methods are usually in the IMessageHandler rather than the IMessage.
So it would look something like this:
public class DoSomething implements IMessage {
// no fields
// empty implementations for every IMessage method
// now the handler, which doesn't have to be a static inner class, but it makes sense to keep them together usually:
public static class HandleDoSomething implements IMessageHandler<DoSomething, IMessage> {
public IMessage onMessage(IMessage message, MessageContext context) {
// all the code that used to be in your KeyInputEvent
}
}
}
Then when the key is pressed, instead of trying to process the result on the client, you instead send the above packet and let it process on the server.
So I have a working packet handler and am sending packets just fine. That's not the thing.
But I have only two Packets registered, one for the client and for the server. What I am doing to actually send data with those two packets is something like this:
package com.github.hashtagshell.hashtagstuff.network.message;
import com.github.hashtagshell.hashtagstuff.handler.event.NetworkMessage;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import io.netty.buffer.ByteBuf;
public class Message implements IMessage, IMessageHandler<Message, IMessage>
{
public String text;
public Message()
{
}
public Message(String text)
{
this.text = text;
}
@Override
public void fromBytes(ByteBuf buf)
{
text = ByteBufUtils.readUTF8String(buf);
}
@Override
public void toBytes(ByteBuf buf)
{
ByteBufUtils.writeUTF8String(buf, text);
}
@Override
public IMessage onMessage(Message m, MessageContext ctx)
{
NetworkMessage.onMessage(m, ctx);
return null;
}
}
EDIT: the NetworkMessage.java class is just a gateway that distributes the args to other classes(e.g. BossHandler.handleMessage(m, ctx))
and on the server side I do
public static void handleMessage(Message m, MessageContext ctx)
{
if (m.text="playerdidsomething")
{
//Do some stuff
}
}
Is it OK (and efficient) to use packets like this or should I create an extending class for each packet?
And then I need to know another thing. I am sending the packet every livingtick while the player is sneaking to the server, which then sets the players falldistance to 0F. Simple code, I know. But isn't this too much network traffic? If yes, how could I reduce it? Or is there another way to make the player take no falldmg while sneaking?
@20Michal No, that is not efficient, and you have a major error in your code:
if (m.text="playerdidsomething")
// using one '=' sign is an assignment, not a comparison
// using two '==' is a comparison, but that is not how you should compare Strings
// for Strings, use the 'equals()' method: if (("sometext").equals(m.text))
Sending and comparing Strings is extremely inefficient compared to the same operations using integers. Define some constants and use those:
public static final int PLAYER_DID_SOMETHING = 1;
// change your message to use an int instead of a String in the constructor, read, and write methods
// then in your handler:
switch (m.action_id) {
case PLAYER_DID_SOMETHING:
// do something
break;
case SOMETHING_ELSE:
// do something else
break;
default: // something went wrong! you got an unexpected integer value:
throw new IllegalArgumentException("Received invalid action id: " + m.action_id);
}
Furthermore, it's much cleaner if you have all the code for processing your packet within the IMessageHandler#onMessage itself, rather than shunting it off to some other class like Minecraft does.
I mean, if you are passing the IMessage to your NetworkMessage#onMessage, it is probably then processing them like 'if (m instanceof IMessage1) { do this } else if (m instanceof IMessage2) { do that }'. What's the point of that when you already have the opportunity to process them within their own handler? Anyway, if that's the way you really want to do it, that's your decision, but I would recommend against it.
That error actually isn't in my code (NetBeans would have corrected me if it was), I was rewriting that code instead of Copy&Pasting my original code.
I know of String.equals(String s) since Netbeans is bugging me with that all the time, I didn't know it was more efficient or whatever (just better). I will start replacing my '=='.
Thank you for the int-idea, since I am using a reference class to ensure the m.text string would be same on both sides it won't be too hard to use ints instead.
And just for your information, this is my actual "gateway class"
public class NetworkMessage
{
public static void onMessage(Message m, MessageContext ctx)
{
HeavenBossHandler.handleMessage(m, ctx);
//AnotherClass.handleMessage(m, ctx);
//...
}
}
And the separate classes would handle their stuff.
But following your recommendation, it will probably end up like this:
public class NetworkMessage
{
public static void onMessage(Message m, MessageContext ctx)
{
switch (m.id)
{
//The HeavenBossHandler class needs to handle both messages
case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_RESETFALLDISTANCE:
HeavenBossHandler.handleMessage(m, ctx);
//FallDistanceResetter2.handleMessage(m, ctx);
case Reference.Network.Packet.ID_DIMENSIONHEAVEN_SETMOVEMENTINPUT:
HeavenBossHandler.handleMessage(m, ctx);
//MovementInputSetupNeeded.handleMessage(m,ctx);
default: {}
}
}
}
I still wonder if I should keep it like this and have the HeavenBossHandler run another switch statement, or have a method for each packet the class handles. But this is more efficient than my previous piece of code, since the classes don't get to handle what they don't need to handle.
And the last thing you recommended me I am thinking about, but what I have setup is something like this:
The classes in the event packages just have the @SubscribeEvent and are registered, and the hand out the event object to the classes in the handler package.
So the HeavenBossHandler looks like this:
public class HeavenBossHandler
{
private static int jumpKeyCooldown = 1;
public static void handleEvent(LivingEvent.LivingUpdateEvent event)
{
...
}
public static void handleEvent(InputEvent.KeyInputEvent event)
{
...
}
public static void handleMessage(Message m, MessageContext ctx)
{
switch (m.id)
{
case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_RESETFALLDISTANCE:
//Reset Server Side Fall distance on ctx.getServerHandler().playerEntity
case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_SETMOVEMENTINPUT:
//Set ClientSide Movement Input on Minecraft.getMinecraft().thePlayer()
}
}
}
As you can see I think of the NetworkMessage.java as of an event, which it in fact is, so I put it into the event package.
The same way the other events get called from forge/fml's respective busses, The NetworkMessage get's called from my Message.java class.
If you need to reference any other code I did not post here, please head to my github repo at https://github.com/HashtagShell/HashtagStuff . It is my first mod and I am learning on it, so it really has some random stuff (aka please don't be mad at me for making a semi-useless mod)
Re: strings - it's not that '==' is less efficient than 'equals', it's that they behave differently. I still recommend you do not send Strings in your packets if you can help it - sending a String across the network is far less efficient than sending an integer.
I think you are making your network code much more complicated than you need to. Rather than having an 'uber' packet that sends what it wants to do as a String, why not make individual packets for each of those actions? See my tutorial demo for some examples.
ok, im trying to use this with the ExtendedPlayer tutorial. it works the first time i enter the world. but then, if i die and hit respawn, it crashes with this report
FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:79) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:136) [NetworkManager.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:414) [NetworkManager.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:374) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:241) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:50) [NetworkDispatcher.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:312) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:44) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel$6.run(LocalChannel.java:298) [LocalChannel$6.class:4.0.15.Final]
at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.15.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [SingleThreadEventExecutor$2.class:4.0.15.Final]
at java.lang.Thread.run(Thread.java:744) [?:1.7.0_51]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:21) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:4.0.15.Final]
... 24 more
[13:14:30] [Netty Local Client IO #0/ERROR]: There was a critical exception handling a packet on channel wheeloftime
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) ~[DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) ~[DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:79) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:136) [NetworkManager.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:414) [NetworkManager.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:374) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:241) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:50) [NetworkDispatcher.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:312) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:44) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel$6.run(LocalChannel.java:298) [LocalChannel$6.class:4.0.15.Final]
at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.15.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [SingleThreadEventExecutor$2.class:4.0.15.Final]
at java.lang.Thread.run(Thread.java:744) [?:1.7.0_51]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:21) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:4.0.15.Final]
... 24 more
does that have to do with this tutorial, and if it does, how do i fix it?
Looks like you are doing something weird with your IMessage registration:
Undefined message for discriminator 0 in channel wheeloftime
Are you per-chance registering your packets in your ClientProxy or some such? You should not do that - the packets need to be registered somewhere where the code is called on both client and server, such as FMLPreInitializationEvent.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumAnything that changes the world state should ALWAYS be done on the server. If you cannot run your code directly on the server side for some reason, then you need to send a packet. Commands, however, are already server side.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumThanks for such quick replies. I appreciate them.
I am having to use the ray trace method, which is client side, and collect the BlockPos of where I'm going to place a block. I found the method, world.rayTraceBlocks(Vec, Vec1, false, false, true), but in order to collect the Vec variables, I need to call a method that is client side only.
EDIT: I made a packet class called Place Block and it is registered. And sorry, I didn't mean command. I got it mixed up
public class PlaceBlock extends AbstractServerMessage<PlaceBlock>
{
private BlockPos pos;
private int x, y, z;
private IBlockState block;
// The basic, no-argument constructor MUST be included to use the new automated handling
public PlaceBlock() {}
// if there are any class fields, be sure to provide a constructor that allows
// for them to be initialized, and use that constructor when sending the packet
public PlaceBlock(int x, int y, int z, IBlockState teraBlock) {
this.pos = new BlockPos(x, y, z);
this.block = teraBlock;
}
@Override
protected void read(PacketBuffer buffer) {
// basic Input/Output operations, very much like DataInputStream
pos = buffer.readBlockPos();
}
@Override
protected void write(PacketBuffer buffer) {
// basic Input/Output operations, very much like DataOutputStream
buffer.writeBlockPos(pos);
}
@Override
public void process(EntityPlayer player, Side side) {
// using the message instance gives access to 'this.id'
player.worldObj.setBlockState(pos, block);
}
And the method that calls it.
//when Right clicked
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player)
{
if(world.isRemote){
lastPos = player.rayTrace(200, 1.0f);
PacketDispatcher.sendToServer(new PlaceBlock(lastPos.getBlockPos().getX(), lastPos.getBlockPos().getY(), lastPos.getBlockPos().getZ(), teraBlock));
}
}
When ran, the game crashes when I right click with the item. I debugged for a while and am not sure why.
I don't mean to make you baby me through this, and by no means do you have to, but I am one of those guys that won't understand how this works until suddenly, for some reason, It clicks and I understand.
Again, thanks for helping
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumonItemUse already has the position and side of the block clicked, so why are you doing all this extra work yourself? If you are trying to place a block very far away, you can still determine the block hit on the server side by copying much of the RayTrace code to make a non-client-only version (there isn't anything really special about it that it needs to be client only, it's mainly just an artifact of decompilation).
As for your error, ALWAYS post a crash report. Makes it way easier to debug.
Your problem is very likely a NullPointerException, because you have to consider that the player may not actually be looking at anything. So if the player is looking up at the sky and right clicks, what do you expect the BlockPos to be? Certainly not a valid block, I'll tell you that much.
I don't know much about java, but I'd like to learn, and am slowly figuring this crap out.
Until I know what I need to know though, I'm a little lost, and could use some help/direction.
So Itoss, the guy who made magiccrusade, told me that to prevent his class selection from popping up on first login, I needed to "Try to send the packet serverside whenever you want, and not when the player login" ... Now I'm happy he responded but I have no fkn clue what he means. I tried searching the sourcecode to find what I needed but I gotta be honest, only certain sections of source make any sense to me right now.
Could someone help me out? I'm not asking for you to straight do it for me, I mean that would be nice, but I understand that you can't help someone who wont help themselves.
Any help appreciated
Aerithis Network Official Website
Minecraft Server Network and Community
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumOn the syncPlayerProps message part of the tutorial. How would I configure that to sync WorldData? Such as a class that extends WorldSavedData.
Thanks again for the tutorial. It's gotten me pretty far into my mod.
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumSorry, I have no idea what he's talking about either. I'm not familiar with that mod, and I'm not really sure what you are doing - are you making another mod that interacts with his mod, or just trying to stop his mod from doing something?
Anyway, it sounds like an issue you need to discuss with the mod maker, or make a general help request in the Modification Development section, as it is not related to this tutorial.
You wouldn't. WorldData is completely separate from IEEP. What are you trying to accomplish, i.e. what, exactly, are you storing in WorldData that you need the client player to know about?
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYou answered my question! I wasn't sure if I was suppose to use packets for it. Now I'm stuck with WorldSavedData not saving. I'll start another thread. Thanks
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumHey there again! I'm having an issue that you may be able to shed some light on.. Hopefully.
So I have an IExtendedEntity class that is edited on the client side. In order for it to update on the server side, would I send the packet to the server?
If so... well, for some reason it isn't being updated on the server side, even when I do dispatch a packet...
Basically, the player stores an IBlockState id. This id is changed when the player is crouching and he presses f, but this can only be done client side.
Here is my packet Dispatcher class. It's the class named 'SyncCurrentMimicBlockState'. It is being registered as Side.CLIENT as well.
http://pastebin.com/Ydv74KaB
SyncCurrentMimicBlockState class
http://pastebin.com/VqRP80NQ
CurrentMimicBlockState class
http://pastebin.com/gjL6dCyC
player input handler
http://pastebin.com/yE3GZLaf
Thanks for all the help!
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYou need to register the packet to the side that will RECEIVE it, not the side that will send it, so it should be Side.SERVER.
What I would do instead of sending all of that data is to send a packet directly from the key press, saying "player A pressed key X", or even "player A is requesting to do action X", then have the server perform the logic that you currently do in your KeyInputEvent. The client should only ever send requests to the server to perform an action and determine the result - it should never be telling the server what the result is directly.
You should use Keyboard.getEventKey() to find the key code of the key pressed, as YourKeyBinding.isPressed() may return true even if it is not the key causing the input event (e.g. the player is holding it down while pressing other keys).
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumIn what case would I use syncCurrentMimicBlockState?
How would I tell the server side to perform such an action?
Makes complete sense! Thanks.
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYou should NEVER have a packet like yours that syncs data from client -> server, only the other way around. You only need to sync from server -> client if the client needs to know about it, e.g. for a GUI.
To have the server perform an action, you send a packet:
1. Player clicks button
2. Packet gets sent: "Player A clicked button X"
3. Server receives packet and does whatever needs to be done for button X
You can do anything you want when processing a packet, not just set variables.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumIs the packet the class that I pass? IE. The SyncCurrentMimicBlockState.class
would I create a different class that holds variables, set those variables, then send that in a packet like I did with SyncCurrentMimicBlockState? (PacketDispatcher.sendToServer(new DoStuff.class))
I complicate easy problems, come begging for help, and leave with a simple solution.

-
View User Profile
-
View Posts
-
Send Message
Curse PremiumYou should research how packets work - it's not a concept unique to Minecraft.
A class, whether it's a 'Packet' or any other class, is just a way to encapsulate information and behavior, but the class definition itself is just that - a definition.
So yes, you would create a new packet class that, within its definition, defines any data (class fields, i.e. variables) that you need to pass to the server (probably none, in your particular case) and then also define some behavior (i.e. methods) that are called when the packet gets processed - that's where things actually happen, and in the case of Minecraft / Forge, those methods are usually in the IMessageHandler rather than the IMessage.
So it would look something like this:
public class DoSomething implements IMessage {Then when the key is pressed, instead of trying to process the result on the client, you instead send the above packet and let it process on the server.// no fields // empty implementations for every IMessage method
// now the handler, which doesn't have to be a static inner class, but it makes sense to keep them together usually: public static class HandleDoSomething implements IMessageHandler<DoSomething, IMessage> { public IMessage onMessage(IMessage message, MessageContext context) { // all the code that used to be in your KeyInputEvent } }
}
So I have a working packet handler and am sending packets just fine. That's not the thing.
But I have only two Packets registered, one for the client and for the server. What I am doing to actually send data with those two packets is something like this:
NetworkWrapper.network.sendToServer(new Message("playerdidsomething"));Where my Message.java is
package com.github.hashtagshell.hashtagstuff.network.message; import com.github.hashtagshell.hashtagstuff.handler.event.NetworkMessage; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; public class Message implements IMessage, IMessageHandler<Message, IMessage> { public String text; public Message() { } public Message(String text) { this.text = text; } @Override public void fromBytes(ByteBuf buf) { text = ByteBufUtils.readUTF8String(buf); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, text); } @Override public IMessage onMessage(Message m, MessageContext ctx) { NetworkMessage.onMessage(m, ctx); return null; } }EDIT: the NetworkMessage.java class is just a gateway that distributes the args to other classes(e.g. BossHandler.handleMessage(m, ctx))
and on the server side I do
public static void handleMessage(Message m, MessageContext ctx) { if (m.text="playerdidsomething") { //Do some stuff } }Is it OK (and efficient) to use packets like this or should I create an extending class for each packet?
And then I need to know another thing. I am sending the packet every livingtick while the player is sneaking to the server, which then sets the players falldistance to 0F. Simple code, I know. But isn't this too much network traffic? If yes, how could I reduce it? Or is there another way to make the player take no falldmg while sneaking?
Thank you
-
View User Profile
-
View Posts
-
Send Message
Curse Premiumif (m.text="playerdidsomething") // using one '=' sign is an assignment, not a comparison // using two '==' is a comparison, but that is not how you should compare Strings // for Strings, use the 'equals()' method: if (("sometext").equals(m.text))Sending and comparing Strings is extremely inefficient compared to the same operations using integers. Define some constants and use those: Furthermore, it's much cleaner if you have all the code for processing your packet within the IMessageHandler#onMessage itself, rather than shunting it off to some other class like Minecraft does.I mean, if you are passing the IMessage to your NetworkMessage#onMessage, it is probably then processing them like 'if (m instanceof IMessage1) { do this } else if (m instanceof IMessage2) { do that }'. What's the point of that when you already have the opportunity to process them within their own handler? Anyway, if that's the way you really want to do it, that's your decision, but I would recommend against it.
That error actually isn't in my code (NetBeans would have corrected me if it was), I was rewriting that code instead of Copy&Pasting my original code.
I know of String.equals(String s) since Netbeans is bugging me with that all the time, I didn't know it was more efficient or whatever (just better). I will start replacing my '=='.
Thank you for the int-idea, since I am using a reference class to ensure the m.text string would be same on both sides it won't be too hard to use ints instead.
And just for your information, this is my actual "gateway class"
public class NetworkMessage { public static void onMessage(Message m, MessageContext ctx) { HeavenBossHandler.handleMessage(m, ctx); //AnotherClass.handleMessage(m, ctx); //... } }And the separate classes would handle their stuff.
But following your recommendation, it will probably end up like this:
public class NetworkMessage { public static void onMessage(Message m, MessageContext ctx) { switch (m.id) { //The HeavenBossHandler class needs to handle both messages case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_RESETFALLDISTANCE: HeavenBossHandler.handleMessage(m, ctx); //FallDistanceResetter2.handleMessage(m, ctx); case Reference.Network.Packet.ID_DIMENSIONHEAVEN_SETMOVEMENTINPUT: HeavenBossHandler.handleMessage(m, ctx); //MovementInputSetupNeeded.handleMessage(m,ctx); default: {} } } }I still wonder if I should keep it like this and have the HeavenBossHandler run another switch statement, or have a method for each packet the class handles. But this is more efficient than my previous piece of code, since the classes don't get to handle what they don't need to handle.
And the last thing you recommended me I am thinking about, but what I have setup is something like this:
net.somebody.something - block, item, reference, tileentity, blablabla - handler - event - LivingHurt.java - LivingDrop.java - NETWORKMESSAGE.JAVA HeavenBossHandler.java AchievementHandler.java PlayerIsLameHandler.java Main.javaThe classes in the event packages just have the @SubscribeEvent and are registered, and the hand out the event object to the classes in the handler package.
So the HeavenBossHandler looks like this:
public class HeavenBossHandler { private static int jumpKeyCooldown = 1; public static void handleEvent(LivingEvent.LivingUpdateEvent event) { ... } public static void handleEvent(InputEvent.KeyInputEvent event) { ... } public static void handleMessage(Message m, MessageContext ctx) { switch (m.id) { case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_RESETFALLDISTANCE: //Reset Server Side Fall distance on ctx.getServerHandler().playerEntity case Reference.Network.Packet.ID_HEAVENBOSSHANDLER_SETMOVEMENTINPUT: //Set ClientSide Movement Input on Minecraft.getMinecraft().thePlayer() } } }As you can see I think of the NetworkMessage.java as of an event, which it in fact is, so I put it into the event package.
The same way the other events get called from forge/fml's respective busses, The NetworkMessage get's called from my Message.java class.
If you need to reference any other code I did not post here, please head to my github repo at https://github.com/HashtagShell/HashtagStuff . It is my first mod and I am learning on it, so it really has some random stuff (aka please don't be mad at me for making a semi-useless mod)
Thanks in advance
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumRe: strings - it's not that '==' is less efficient than 'equals', it's that they behave differently. I still recommend you do not send Strings in your packets if you can help it - sending a String across the network is far less efficient than sending an integer.
I think you are making your network code much more complicated than you need to. Rather than having an 'uber' packet that sends what it wants to do as a String, why not make individual packets for each of those actions? See my tutorial demo for some examples.
ok, im trying to use this with the ExtendedPlayer tutorial. it works the first time i enter the world. but then, if i die and hit respawn, it crashes with this report
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:79) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:136) [NetworkManager.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:414) [NetworkManager.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:374) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:241) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:50) [NetworkDispatcher.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:312) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:44) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel$6.run(LocalChannel.java:298) [LocalChannel$6.class:4.0.15.Final]
at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.15.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [SingleThreadEventExecutor$2.class:4.0.15.Final]
at java.lang.Thread.run(Thread.java:744) [?:1.7.0_51]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:21) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:4.0.15.Final]
... 24 more
[13:14:30] [Netty Local Client IO #0/ERROR]: There was a critical exception handling a packet on channel wheeloftime
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) ~[DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) ~[DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:79) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:136) [NetworkManager.class:?]
at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:414) [NetworkManager.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:374) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:241) [NetworkDispatcher.class:?]
at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:50) [NetworkDispatcher.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103) [SimpleChannelInboundHandler.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) [DefaultChannelHandlerContext.class:4.0.15.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:312) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:44) [LocalChannel.class:4.0.15.Final]
at io.netty.channel.local.LocalChannel$6.run(LocalChannel.java:298) [LocalChannel$6.class:4.0.15.Final]
at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.15.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [SingleThreadEventExecutor$2.class:4.0.15.Final]
at java.lang.Thread.run(Thread.java:744) [?:1.7.0_51]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel wheeloftime
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:21) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:4.0.15.Final]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:4.0.15.Final]
... 24 more
does that have to do with this tutorial, and if it does, how do i fix it?
-
View User Profile
-
View Posts
-
Send Message
Curse Premiumactually, i entirely forgot to register the packet handler.