I have an arraylist of custom objects that is produced server side. How can I sync these values with the client side? My arraylist is static and not attached to entities, so I don't think custom NBT data will work. Thanks in advance for any suggestions!
You would have to send it through a packet, if the list is only generated on the server side. What type of data does your custom object require? You should be able to make your own writeToNBT and readFromNBT methods and pair it with a packet.
My object consists mostly of blocks and metadata values. The issue is that it can contain hundreds of entries. Do you know of any good packet tutorials? How would I pair it with NBT?
My object consists mostly of blocks and metadata values. The issue is that it can contain hundreds of entries. Do you know of any good packet tutorials? How would I pair it with NBT?
If it is extremely large, then you don't want to use packets. That would just lag everything out. What is the purpose of this object?
I have a configuration file of possible blocks my custom mob can imitate. (See the ore sheep mod.) The player can add block names to this file. However, when the server and client config files are different, rendering glitches can occur. For example, if the client has a block the server doesn't, when the player tries to change the sheep to that block, it appears to change on client, but no on server. Vice versa, if the server has a block the client doesn't, the sheep of that block isn't rendered client side.
In summary, I need a large group of block references to sync from server to client.
The Meaning of Life, the Universe, and Everything.
Join Date:
10/12/2013
Posts:
50
Member Details
Just send it as a packet, you'll only need to send it on login so it shouldn't really affect performance. If it's seriously too large for that then pack the data and zip it and then send it on login
The forge documentation on networking is pretty good.
One more note -- you don't want to send the actual objects in the packet payload, but just enough information that the client side can re-create the objects/list. For example, for the blocks maybe you want to send the unlocalized name, or you can come up with a custom ID system using integers.
I'm having some issues getting it set up. To test my new packet handler, I have it give the client 7 diamonds when they log in. However, whenever the player logs in, I get this error message:
[10:20:10] [Client thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception
java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
at cpw.mods.fml.common.network.simpleimpl.MessageContext.getServerHandler(MessageContext.java:36) ~[MessageContext.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:18) ~[OreSheepMessageHandler.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:1) ~[OreSheepMessageHandler.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:37) ~[SimpleChannelHandlerWrapper.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:17) ~[SimpleChannelHandlerWrapper.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98) ~[SimpleChannelInboundHandler.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) [MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.multiplayer.GuiConnecting.updateScreen(GuiConnecting.java:116) [GuiConnecting.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1741) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
[10:20:10] [Client thread/ERROR] [FML]: There was a critical exception handling a packet on channel oresheepmod
java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
at cpw.mods.fml.common.network.simpleimpl.MessageContext.getServerHandler(MessageContext.java:36) ~[MessageContext.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:18) ~[OreSheepMessageHandler.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:1) ~[OreSheepMessageHandler.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:37) ~[SimpleChannelHandlerWrapper.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:17) ~[SimpleChannelHandlerWrapper.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98) ~[SimpleChannelInboundHandler.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.multiplayer.GuiConnecting.updateScreen(GuiConnecting.java:116) [GuiConnecting.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1741) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
The client then displays:
Connection Lost
A fatal error has occured, this connection is terminated.
Okay, here is my code:
In the mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
@SubscribeEvent
@SideOnly(Side.SERVER) // I thought this line would fix the exception, but it didn't
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
System.out.println("Sending message test.... "); //test if the message goes through
ModOreSheep.INSTANCE.sendTo(new BeBlocksServerMessage(7), (EntityPlayerMP) event.player);
}
public class BeBlocksServerMessage implements IMessage
{
// A default constructor is always required
public BeBlocksServerMessage(){}
private int toSend;
public BeBlocksServerMessage(int toSend)
{
this.toSend = toSend;
}
@Override
public void toBytes(ByteBuf buf)
{
// Writes the int into the buf
buf.writeInt(toSend);
}
@Override
public void fromBytes(ByteBuf buf)
{
// Reads the int back from the buf. Note that if you have multiple values, you must read in the same order you wrote.
toSend = buf.readInt();
}
//The params of the IMessageHandler are <REQ, REPLY>, meaning that the first is the packet you are receiving, and the second is the packet you are returning. The returned packet can be used as a "response" from a sent packet.
public class OreSheepMessageHandler implements IMessageHandler<BeBlocksServerMessage, IMessage>
{
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(BeBlocksServerMessage message, MessageContext ctx)
{
// This is the player the packet was sent to the server from
EntityPlayerMP serverPlayer = ctx.getServerHandler().playerEntity;
// The value that was sent
int amount = message.getToSend();
serverPlayer.inventory.addItemStackToInventory(new ItemStack(Items.diamond, amount));
// No response packet
return null;
}
}
I followed the tutorial given by Darkhax. It said that, for the sendTo command "as long as you are on the server you can safely cast any EntityPlayer to EntityPlayerMP." Is the client executing the the code when it shouldn't or is there another error I have made? Thanks!
I have a configuration file of possible blocks my custom mob can imitate. (See the ore sheep mod.) The player can add block names to this file. However, when the server and client config files are different, rendering glitches can occur. For example, if the client has a block the server doesn't, when the player tries to change the sheep to that block, it appears to change on client, but no on server. Vice versa, if the server has a block the client doesn't, the sheep of that block isn't rendered client side.
In summary, I need a large group of block references to sync from server to client.
This sounds like you may be having a slightly different problem than you are looking at.
You should never spawn a block on the client side, only spawn them on the server. Same goes for entities, and just about anything.
The client will sync to the server world when something is spawned, but the server will never sync to the client world.
I'm not spawning any blocks, but could adding diamonds to the player's inventory be the problem? I believe the issue is a cast of the the net.minecraft.client.network.NetHandlerPlayClient to the net.minecraft.network.NetHandlerPlayServer. What I need is only the server to send a message and only the client to receive it. How can I ensure that their roles don't mix?
Edit: Oh there may be a misunderstanding. The config file tells the sheep what blocks they can appear to be. I want my config file to only apply server side, but communicate to the client the resulting ArrayList. Afterward, the client reads the ArrayList of blocks and draws textures for each one. When there is a mismatch between the arraylists, rendering issues occur.
So yes, you can send packets just to the client. The function to send them is actually different for client and server, so use the right one. To send an arrayList, you would send just the Block IDs and then recreate the array at the other end (I think).
Hmm, just looked at your code. I think there may be a problem with how the packets work, but you've laid it out different than I've seen, so it is hard to tell. I'll see if I can look at this later when I have more time.
Okay, I've done some rearranging (renaming and reorganizing) of the code to match some tutorial formats. I also chose to skip testing to start working on the actual methods I intend to use. I now have a new error.
[14:28:05] [Client thread/ERROR] [FML]: FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
[14:28:05] [Client thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
[14:28:05] [Client thread/ERROR] [FML]: There was a critical exception handling a packet on channel oresheepmod
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
The client still displays:
Connection Lost
A fatal error has occured, this connection is terminated.
Here is my code:
From main mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
@SubscribeEvent
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
Side side = FMLCommonHandler.instance().getEffectiveSide();
if (side == Side.SERVER)
{
System.out.println("Sending message test.... "); //test if the code works
ModOreSheep.INSTANCE.sendTo(new ServerConfigPacket(OreRegistryDraw.getBeBlocks()), (EntityPlayerMP) event.player);
}
}
public class ServerConfigPacket implements IMessage
{
// A default constructor is always required
public ServerConfigPacket(){}
ArrayList<Integer> beBlockInts = new ArrayList<Integer>();
/********/the parameter here is my array of block objects
public ServerConfigPacket(ArrayList<BlockEntry> beBlocks)
{
//first integer is the size of the array
beBlockInts.add(beBlocks.size());
//the rest of the integers are stored the same way an ore sheep stores an integer, by block id*100 + meta of each block
for (BlockEntry k : beBlocks)
{
@Override
public void toBytes(ByteBuf buf)
{
for (int k : beBlockInts)
{
buf.writeInt(k);
}
}
@Override
public void fromBytes(ByteBuf buf)
{
beBlockInts = new ArrayList<Integer>();
for (int i = 0; i <buf.readInt(); i++)
{
beBlockInts.add(buf.readInt());
}
}
public ArrayList<Integer> getToSend()
{
return beBlockInts;
}
//I put this class inside the other packet class
public static class OreSheepHandler implements IMessageHandler<ServerConfigPacket, IMessage>
{
@Override
public IMessage onMessage(ServerConfigPacket message, MessageContext ctx)
{
for (int k : message.getToSend())
{
System.out.println(k);
}
// No response packet
return null;
}
}
}
What is the max size of a ByteBuf? I seem to be going way over it. Any ideas for how to fit all of my values?
There is a limit I'm sure, it is pretty large I think.
What you need to do, is write exactly the same number of bytes as you read. So if you have a loop like you do. The first thing you would do is write the number of ints you are going to write, and then write just that many. You then on the read side read that first, and read just that many.
So far I've just done individual ints. I've done just four reads and four writes all to separate variables.
You have the size of your array in the first write, but having this:
for (int i = 0; i <buf.readInt(); i++)
Is that just reading the size once, or every time in the loop?
Almost everything works now. There's still a problem with single player worlds however. The server side on single player worlds doesn't seem to execute the same code as the dedicated server, completely skipping over the packets. In my mod, the server side needs to read the config and pass it to the client, whether that be a single player client or a client connecting to a dedicated server. Any ideas why this doesn't work in single player?
Here is my code:
From the main mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
//don't do FMLCommonHandler.instance().getEffectiveSide() here because it only works on dedicated servers and crashes in single player
@SideOnly(Side.SERVER)
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
ModOreSheep.INSTANCE.sendTo(new ServerConfigPacket(OreRegistryDraw.getBeBlocks()), (EntityPlayerMP) event.player);
}
public class ServerConfigPacket implements IMessage
{
// A default constructor is always required
public ServerConfigPacket(){}
ArrayList beBlockInts = new ArrayList();
int length = 0;
public ServerConfigPacket(ArrayList beBlocks)
{
//size of the array
//the rest of the integers are stored the same way an ore sheep stores an integer, by block id + meta
for (int i = 0; i < beBlocks.size(); i++)
{
BlockEntry k = beBlocks.get(i);
int value = (k.getBlock().getIdFromBlock(k.getBlock())* 100) + k.getMeta();
beBlockInts.add(value);
}
length = beBlockInts.size();
}
@Override
public void toBytes(ByteBuf buf)
{
buf.writeInt(length);
for (int k : beBlockInts)
{
buf.writeInt(k);
}
}
@Override
public void fromBytes(ByteBuf buf)
{
// Reads the int back from the buf. Note that if you have multiple values, you must read in the same order you wrote.
beBlockInts = new ArrayList();
int length = buf.readInt();
for (int i = 0; i < length; i++)
{
beBlockInts.add(buf.readInt());
}
}
public ArrayList getToSend()
{
return beBlockInts;
}
//The params of the IMessageHandler are <req, reply="">, meaning that the first is the packet you are receiving, and the second is the packet you are returning. The returned packet can be used as a "response" from a sent packet.
public static class OreSheepHandler implements IMessageHandler<serverconfigpacket, imessage="">
{
@Override
public IMessage onMessage(ServerConfigPacket message, MessageContext ctx)
{
ArrayList ints = message.getToSend();
//TODO
ArrayList beBlocks = new ArrayList();
for (Integer i : ints)
{
Block block = Block.getBlockById((int)((double)i / 100));
//if block isn't legal
if (!OreRegistryDraw.isBlockLegal(block) || block.equals(Blocks.air))
{
continue;
}
byte met = (byte) (i % 100);
beBlocks.add(new BlockEntry(block, met));
}
OreRegistryDraw.setBeBlocks(beBlocks);
// No response packet
return null;
}
}
}
I have an arraylist of custom objects that is produced server side. How can I sync these values with the client side? My arraylist is static and not attached to entities, so I don't think custom NBT data will work. Thanks in advance for any suggestions!
You would have to send it through a packet, if the list is only generated on the server side. What type of data does your custom object require? You should be able to make your own writeToNBT and readFromNBT methods and pair it with a packet.
Farewell everyone o/
My object consists mostly of blocks and metadata values. The issue is that it can contain hundreds of entries. Do you know of any good packet tutorials? How would I pair it with NBT?
If it is extremely large, then you don't want to use packets. That would just lag everything out. What is the purpose of this object?
Farewell everyone o/
I have a configuration file of possible blocks my custom mob can imitate. (See the ore sheep mod.) The player can add block names to this file. However, when the server and client config files are different, rendering glitches can occur. For example, if the client has a block the server doesn't, when the player tries to change the sheep to that block, it appears to change on client, but no on server. Vice versa, if the server has a block the client doesn't, the sheep of that block isn't rendered client side.
In summary, I need a large group of block references to sync from server to client.
Just send it as a packet, you'll only need to send it on login so it shouldn't really affect performance. If it's seriously too large for that then pack the data and zip it and then send it on login
The forge documentation on networking is pretty good.
This is YOUTUBE
Thanks Purebee and Darkhax! I'll check out the material you've given me and post results/ questions if I have any.
One more note -- you don't want to send the actual objects in the packet payload, but just enough information that the client side can re-create the objects/list. For example, for the blocks maybe you want to send the unlocalized name, or you can come up with a custom ID system using integers.
I'm having some issues getting it set up. To test my new packet handler, I have it give the client 7 diamonds when they log in. However, whenever the player logs in, I get this error message:
[10:20:10] [Client thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception
java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
at cpw.mods.fml.common.network.simpleimpl.MessageContext.getServerHandler(MessageContext.java:36) ~[MessageContext.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:18) ~[OreSheepMessageHandler.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:1) ~[OreSheepMessageHandler.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:37) ~[SimpleChannelHandlerWrapper.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:17) ~[SimpleChannelHandlerWrapper.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98) ~[SimpleChannelInboundHandler.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) [MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.multiplayer.GuiConnecting.updateScreen(GuiConnecting.java:116) [GuiConnecting.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1741) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
[10:20:10] [Client thread/ERROR] [FML]: There was a critical exception handling a packet on channel oresheepmod
java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
at cpw.mods.fml.common.network.simpleimpl.MessageContext.getServerHandler(MessageContext.java:36) ~[MessageContext.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:18) ~[OreSheepMessageHandler.class:?]
at oresheepmod.OreSheepMessageHandler.onMessage(OreSheepMessageHandler.java:1) ~[OreSheepMessageHandler.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:37) ~[SimpleChannelHandlerWrapper.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:17) ~[SimpleChannelHandlerWrapper.class:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98) ~[SimpleChannelInboundHandler.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.multiplayer.GuiConnecting.updateScreen(GuiConnecting.java:116) [GuiConnecting.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1741) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
The client then displays:
Connection Lost
A fatal error has occured, this connection is terminated.
Okay, here is my code:
In the mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
@EventHandler
public void load(FMLInitializationEvent event)
{
INSTANCE.registerMessage(OreSheepMessageHandler.class, BeBlocksServerMessage.class, 0, Side.CLIENT);
MinecraftForge.EVENT_BUS.register(new OreSheepEventHandler());
FMLCommonHandler.instance().bus().register(new OreSheepEventHandler());
}
In the OreSheepEventHandler
@SubscribeEvent
@SideOnly(Side.SERVER) // I thought this line would fix the exception, but it didn't
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
System.out.println("Sending message test.... "); //test if the message goes through
ModOreSheep.INSTANCE.sendTo(new BeBlocksServerMessage(7), (EntityPlayerMP) event.player);
}
BeBlocksServerMessage
package oresheepmod;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
public class BeBlocksServerMessage implements IMessage
{
// A default constructor is always required
public BeBlocksServerMessage(){}
private int toSend;
public BeBlocksServerMessage(int toSend)
{
this.toSend = toSend;
}
@Override
public void toBytes(ByteBuf buf)
{
// Writes the int into the buf
buf.writeInt(toSend);
}
@Override
public void fromBytes(ByteBuf buf)
{
// Reads the int back from the buf. Note that if you have multiple values, you must read in the same order you wrote.
toSend = buf.readInt();
}
public int getToSend()
{
return toSend;
}
}
OreSheepMessageHandler
package oresheepmod;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
//The params of the IMessageHandler are <REQ, REPLY>, meaning that the first is the packet you are receiving, and the second is the packet you are returning. The returned packet can be used as a "response" from a sent packet.
public class OreSheepMessageHandler implements IMessageHandler<BeBlocksServerMessage, IMessage>
{
// Do note that the default constructor is required, but implicitly defined in this case
@Override
public IMessage onMessage(BeBlocksServerMessage message, MessageContext ctx)
{
// This is the player the packet was sent to the server from
EntityPlayerMP serverPlayer = ctx.getServerHandler().playerEntity;
// The value that was sent
int amount = message.getToSend();
serverPlayer.inventory.addItemStackToInventory(new ItemStack(Items.diamond, amount));
// No response packet
return null;
}
}
I followed the tutorial given by Darkhax. It said that, for the sendTo command "as long as you are on the server you can safely cast any EntityPlayer to EntityPlayerMP." Is the client executing the the code when it shouldn't or is there another error I have made? Thanks!
This sounds like you may be having a slightly different problem than you are looking at.
You should never spawn a block on the client side, only spawn them on the server. Same goes for entities, and just about anything.
The client will sync to the server world when something is spawned, but the server will never sync to the client world.
[url=2482915-wip-arkcraft-survival-evolved-dinos-taming]
I'm not spawning any blocks, but could adding diamonds to the player's inventory be the problem? I believe the issue is a cast of the the net.minecraft.client.network.NetHandlerPlayClient to the net.minecraft.network.NetHandlerPlayServer. What I need is only the server to send a message and only the client to receive it. How can I ensure that their roles don't mix?
Edit: Oh there may be a misunderstanding. The config file tells the sheep what blocks they can appear to be. I want my config file to only apply server side, but communicate to the client the resulting ArrayList. Afterward, the client reads the ArrayList of blocks and draws textures for each one. When there is a mismatch between the arraylists, rendering issues occur.
Once you've done it a few times, this network packet tutorial does seem simple, but not at first:
http://www.minecraftforge.net/forum/index.php/topic,20135.0.html
So yes, you can send packets just to the client. The function to send them is actually different for client and server, so use the right one. To send an arrayList, you would send just the Block IDs and then recreate the array at the other end (I think).
Hmm, just looked at your code. I think there may be a problem with how the packets work, but you've laid it out different than I've seen, so it is hard to tell. I'll see if I can look at this later when I have more time.
[url=2482915-wip-arkcraft-survival-evolved-dinos-taming]
Okay, I've done some rearranging (renaming and reorganizing) of the code to match some tutorial formats. I also chose to skip testing to start working on the actual methods I intend to use. I now have a new error.
[14:28:05] [Client thread/ERROR] [FML]: FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
[14:28:05] [Client thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
[14:28:05] [Client thread/ERROR] [FML]: There was a critical exception handling a packet on channel oresheepmod
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2141) [Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) [Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_40]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(1940) + length(4) exceeds writerIndex(1940): SlicedByteBuf(ridx: 1940, widx: 1940, cap: 1940/1940, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 1941, cap: 1941/1941))
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?]
at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:611) ~[AbstractByteBuf.class:?]
at oresheepmod.ServerConfigPacket.fromBytes(ServerConfigPacket.java:46) ~[ServerConfigPacket.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[SimpleIndexedCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?]
at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 19 more
The client still displays:
Connection Lost
A fatal error has occured, this connection is terminated.
Here is my code:
From main mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
@EventHandler
public void load(FMLInitializationEvent event)
{
INSTANCE.registerMessage(OreSheepHandler.class, ServerConfigPacket.class, 0, Side.CLIENT);
MinecraftForge.EVENT_BUS.register(new OreSheepEventHandler());
FMLCommonHandler.instance().bus().register(new OreSheepEventHandler());
}
From EventHandler:
@SubscribeEvent
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
Side side = FMLCommonHandler.instance().getEffectiveSide();
if (side == Side.SERVER)
{
System.out.println("Sending message test.... "); //test if the code works
ModOreSheep.INSTANCE.sendTo(new ServerConfigPacket(OreRegistryDraw.getBeBlocks()), (EntityPlayerMP) event.player);
}
}
ServerConfigPacket
package oresheepmod;
import java.util.ArrayList;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
public class ServerConfigPacket implements IMessage
{
// A default constructor is always required
public ServerConfigPacket(){}
ArrayList<Integer> beBlockInts = new ArrayList<Integer>();
/********/the parameter here is my array of block objects
public ServerConfigPacket(ArrayList<BlockEntry> beBlocks)
{
//first integer is the size of the array
beBlockInts.add(beBlocks.size());
//the rest of the integers are stored the same way an ore sheep stores an integer, by block id*100 + meta of each block
for (BlockEntry k : beBlocks)
{
beBlockInts.add((k.getBlock().getIdFromBlock(k.getBlock()) * 100) + k.getMeta());
}
}
@Override
public void toBytes(ByteBuf buf)
{
for (int k : beBlockInts)
{
buf.writeInt(k);
}
}
@Override
public void fromBytes(ByteBuf buf)
{
beBlockInts = new ArrayList<Integer>();
for (int i = 0; i <buf.readInt(); i++)
{
beBlockInts.add(buf.readInt());
}
}
public ArrayList<Integer> getToSend()
{
return beBlockInts;
}
//I put this class inside the other packet class
public static class OreSheepHandler implements IMessageHandler<ServerConfigPacket, IMessage>
{
@Override
public IMessage onMessage(ServerConfigPacket message, MessageContext ctx)
{
for (int k : message.getToSend())
{
System.out.println(k);
}
// No response packet
return null;
}
}
}
What is the max size of a ByteBuf? I seem to be going way over it. Any ideas for how to fit all of my values?
There is a limit I'm sure, it is pretty large I think.
What you need to do, is write exactly the same number of bytes as you read. So if you have a loop like you do. The first thing you would do is write the number of ints you are going to write, and then write just that many. You then on the read side read that first, and read just that many.
So far I've just done individual ints. I've done just four reads and four writes all to separate variables.
You have the size of your array in the first write, but having this:
for (int i = 0; i <buf.readInt(); i++)
Is that just reading the size once, or every time in the loop?
Might be safer to do:
int size = buf.readInt();
for (int i = 0; i < size; i++)
[url=2482915-wip-arkcraft-survival-evolved-dinos-taming]
Edit:
Almost everything works now. There's still a problem with single player worlds however. The server side on single player worlds doesn't seem to execute the same code as the dedicated server, completely skipping over the packets. In my mod, the server side needs to read the config and pass it to the client, whether that be a single player client or a client connecting to a dedicated server. Any ideas why this doesn't work in single player?
Here is my code:
From the main mod class:
public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(modid);
@EventHandler
public void load(FMLInitializationEvent event)
{
INSTANCE.registerMessage(OreSheepHandler.class, ServerConfigPacket.class, 0, Side.CLIENT);
MinecraftForge.EVENT_BUS.register(new OreSheepEventHandler());
FMLCommonHandler.instance().bus().register(new OreSheepEventHandler());
}
From OreSheepEventHandler:
@SubscribeEvent
//don't do FMLCommonHandler.instance().getEffectiveSide() here because it only works on dedicated servers and crashes in single player
@SideOnly(Side.SERVER)
public void onLogIn(PlayerEvent.PlayerLoggedInEvent event)
{
ModOreSheep.INSTANCE.sendTo(new ServerConfigPacket(OreRegistryDraw.getBeBlocks()), (EntityPlayerMP) event.player);
}
ServerConfigPacket
package oresheepmod;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
public class ServerConfigPacket implements IMessage
{
// A default constructor is always required
public ServerConfigPacket(){}
ArrayList beBlockInts = new ArrayList();
int length = 0;
public ServerConfigPacket(ArrayList beBlocks)
{
//size of the array
//the rest of the integers are stored the same way an ore sheep stores an integer, by block id + meta
for (int i = 0; i < beBlocks.size(); i++)
{
BlockEntry k = beBlocks.get(i);
int value = (k.getBlock().getIdFromBlock(k.getBlock())* 100) + k.getMeta();
beBlockInts.add(value);
}
length = beBlockInts.size();
}
@Override
public void toBytes(ByteBuf buf)
{
buf.writeInt(length);
for (int k : beBlockInts)
{
buf.writeInt(k);
}
}
@Override
public void fromBytes(ByteBuf buf)
{
// Reads the int back from the buf. Note that if you have multiple values, you must read in the same order you wrote.
beBlockInts = new ArrayList();
int length = buf.readInt();
for (int i = 0; i < length; i++)
{
beBlockInts.add(buf.readInt());
}
}
public ArrayList getToSend()
{
return beBlockInts;
}
//The params of the IMessageHandler are <req, reply="">, meaning that the first is the packet you are receiving, and the second is the packet you are returning. The returned packet can be used as a "response" from a sent packet.
public static class OreSheepHandler implements IMessageHandler<serverconfigpacket, imessage="">
{
@Override
public IMessage onMessage(ServerConfigPacket message, MessageContext ctx)
{
ArrayList ints = message.getToSend();
//TODO
ArrayList beBlocks = new ArrayList();
for (Integer i : ints)
{
Block block = Block.getBlockById((int)((double)i / 100));
//if block isn't legal
if (!OreRegistryDraw.isBlockLegal(block) || block.equals(Blocks.air))
{
continue;
}
byte met = (byte) (i % 100);
beBlocks.add(new BlockEntry(block, met));
}
OreRegistryDraw.setBeBlocks(beBlocks);
// No response packet
return null;
}
}
}