Jump to content

[1.11.2] SimpleNetworkWrapper - Undefined message for descriptor 0 in channel


Recommended Posts

Posted

So I have created a coloured block which saves its colour in a tile entity and can be coloured using a coloured item (paint brush) using its NBT. Currently my tile entity works fine and the block works correctly until I break the block where when I do, I don't get the coloured block but a white version of my coloured block. I have tried to fix this using a SimpleNetworkWrapper having a message sent to the server when I break the block to then receive the tile entity data to then spawn the item. Unfortunately this does not work as the following error occurs:

[Netty Server IO #1/ERROR] [FML]: FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel boe
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:111) [FMLProxyPacket.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:157) [NetworkManager.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:51) [NetworkManager.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleServerSideCustomPacket(NetworkDispatcher.java:452) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:274) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:73) [NetworkDispatcher.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:326) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:45) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel$5.run(LocalChannel.java:312) [LocalChannel$5.class:4.0.23.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380) [SingleThreadEventExecutor.class:4.0.23.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357) [NioEventLoop.class:4.0.23.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [SingleThreadEventExecutor$2.class:4.0.23.Final]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_121]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel boe
	at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:99) ~[FMLIndexedMessageToMessageCodec.class:?]
	at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:40) ~[FMLIndexedMessageToMessageCodec.class:?]
	at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:4.0.23.Final]
	... 25 more

I have seen people have this error before and by looking on the forums I have found a solution which stops the error but does not fix the block dropping correctly.

I have noticed that when (in my ClientProxy) I register the message like so:

BitOfEverything.network.registerMessage(CanvasItemDropMessageHandler.class, CanvasItemDropMessage.class, Reference.PACKET_ID_CANVAS, Side.CLIENT);

the error does not occur. When I remove this I get the previous error. And my packet id is not 0 it is actually 30.

 

I currently send my packet here:

In my block class:

@Override
public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te, ItemStack stack) {
	if(!world.isRemote)
		BitOfEverything.network.sendToServer(new CanvasItemDropMessage(pos));
}

 

Now one thing I do notice is that in my packet handler:

public static class CanvasItemDropMessageHandler implements IMessageHandler<CanvasItemDropMessage, IMessage> {

	@Override
	public IMessage onMessage(CanvasItemDropMessage message, MessageContext ctx) {
		Utils.getLogger().info("Handling message! " + ctx.side.toString());
		if(ctx.side == Side.SERVER && message.messageValid) {
			if(ctx.getServerHandler().playerEntity == null) return null;
			ctx.getServerHandler().playerEntity.getServerWorld().addScheduledTask(new Runnable() {
					
				@Override
				public void run() {
					Utils.getLogger().info("Server side!");
					TileEntityCanvas canvas = (TileEntityCanvas) ctx.getServerHandler().playerEntity.getServerWorld().getTileEntity(message.pos);
					spawnEntity(ctx.getServerHandler().playerEntity.getServerWorld(), canvas, message.pos);
				}
			});
	
		}
		return null;
	}
  
	void spawnEntity(World world, TileEntityCanvas canvas, BlockPos pos) {
		if(!world.isRemote && world.getGameRules().getBoolean("doTileDrops") && !world.restoringBlockSnapshots) {
			ItemStack stack = new ItemStack(ModBlocks.canvas);
			NBTTagCompound nbt = new NBTTagCompound();
			nbt.setInteger("colour", canvas.getColour());
			stack.setTagCompound(nbt);
	   		float f = 0.5F;
	        	double d0 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	        	double d1 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	        	double d2 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	        	EntityItem entityitem = new EntityItem(world, (double)pos.getX() + d0, (double)pos.getY() + d1, (double)pos.getZ() + d2, stack);
			entityitem.setDefaultPickupDelay();
	    		world.spawnEntity(entityitem);
	    		Utils.getLogger().info("Spawned the item!");
		}
	}
}

The handling message console message never occurs. It seems like my message either never hits the server or there is an error on the way. I'm not to sure what it is and I am intrigued to know my error.

 

Just for use here is the code which seems relevant:

The message and handler:

package cjminecraft.bitofeverything.packets;

import cjminecraft.bitofeverything.BitOfEverything;
import cjminecraft.bitofeverything.init.ModBlocks;
import cjminecraft.bitofeverything.tileentity.TileEntityCanvas;
import cjminecraft.bitofeverything.util.Utils;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.SPacketSpawnObject;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;

public class CanvasItemDropMessage implements IMessage {

	private boolean messageValid;
	
	private BlockPos pos;
	
	public CanvasItemDropMessage() {
		this.messageValid = false;
	}
	
	public CanvasItemDropMessage(BlockPos pos) {
		this.pos = pos;
		this.messageValid = true;
	}
	
	@Override
	public void fromBytes(ByteBuf buf) {
		try {
			this.pos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
		} catch (IndexOutOfBoundsException ioe) {
			Utils.getLogger().info(ioe.getMessage());
			return;
		}
		this.messageValid = true;
	}

	@Override
	public void toBytes(ByteBuf buf) {
		if(!this.messageValid) return;
		buf.writeInt(this.pos.getX());
		buf.writeInt(this.pos.getY());
		buf.writeInt(this.pos.getZ());
	}
	
	public static class CanvasItemDropMessageHandler implements IMessageHandler<CanvasItemDropMessage, IMessage> {

		@Override
		public IMessage onMessage(CanvasItemDropMessage message, MessageContext ctx) {
			Utils.getLogger().info("Handling message! " + ctx.side.toString());
			if(ctx.side == Side.SERVER && message.messageValid) {
				if(ctx.getServerHandler().playerEntity == null) return null;
				ctx.getServerHandler().playerEntity.getServerWorld().addScheduledTask(new Runnable() {
					
					@Override
					public void run() {
						Utils.getLogger().info("Server side!");
						TileEntityCanvas canvas = (TileEntityCanvas) ctx.getServerHandler().playerEntity.getServerWorld().getTileEntity(message.pos);
						spawnEntity(ctx.getServerHandler().playerEntity.getServerWorld(), canvas, message.pos);
					}
				});
				
			}
			return null;
		}
		
		void spawnEntity(World world, TileEntityCanvas canvas, BlockPos pos) {
			if(!world.isRemote && world.getGameRules().getBoolean("doTileDrops") && !world.restoringBlockSnapshots) {
				ItemStack stack = new ItemStack(ModBlocks.canvas);
				NBTTagCompound nbt = new NBTTagCompound();
				nbt.setInteger("colour", canvas.getColour());
				stack.setTagCompound(nbt);
				float f = 0.5F;
	            double d0 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	            double d1 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	            double d2 = (double)(world.rand.nextFloat() * 0.5F) + 0.25D;
	            EntityItem entityitem = new EntityItem(world, (double)pos.getX() + d0, (double)pos.getY() + d1, (double)pos.getZ() + d2, stack);
	            entityitem.setDefaultPickupDelay();
	            world.spawnEntity(entityitem);
	            Utils.getLogger().info("Spawned the item!");
			}
		}
		
	}

}

The block:

package cjminecraft.bitofeverything.blocks;

import java.util.ArrayList;
import java.util.List;

import cjminecraft.bitofeverything.BitOfEverything;
import cjminecraft.bitofeverything.Reference;
import cjminecraft.bitofeverything.init.ModBlocks;
import cjminecraft.bitofeverything.init.ModItems;
import cjminecraft.bitofeverything.packets.CanvasItemDropMessage;
import cjminecraft.bitofeverything.tileentity.TileEntityCanvas;
import cjminecraft.bitofeverything.util.Utils;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;

/**
 * A block which can be coloured when clicked on by a paint brush
 * @author CJMinecraft
 *
 */
public class BlockCanvas extends BlockContainer implements ITileEntityProvider {

	/**
	 * Default block constructor
	 * @param unlocalizedName The unlocalised name of the block
	 */
	public BlockCanvas(String unlocalizedName) {
		super(Material.CLOTH);
		this.setUnlocalizedName(unlocalizedName);
		this.setRegistryName(new ResourceLocation(Reference.MODID, unlocalizedName));
		this.setHardness(1);
		this.setResistance(5);
		this.isBlockContainer = true; //Says it is a block container
	}
	
	/**
	 * This will change the blocks colour when clicked on by a paint brush
	 */
	@Override
	public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		if(player.getHeldItem(hand).getItem() == ModItems.paintBrush) {
			TileEntityCanvas canvas = (TileEntityCanvas) world.getTileEntity(pos);
			canvas.setColour(player.getHeldItem(hand).getTagCompound().getInteger("colour"));
			world.markBlockRangeForRenderUpdate(pos, pos);
		}
		return false;
	}
	
	/**
	 * Says what colour the block is
	 */
	@Override
	public void addInformation(ItemStack stack, EntityPlayer player, List<String> tooltip, boolean advanced) {
		if(stack.hasTagCompound())
			if(stack.getTagCompound().hasKey("colour"))
				tooltip.add(TextFormatting.GRAY + I18n.format(getUnlocalizedName() + ".tooltip", String.format("#%06X", (0xFFFFFF & stack.getTagCompound().getInteger("colour")))));
	}
	
	/**
	 * Makes it so that when you pick block, you get the correct block
	 */
	@Override
	public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos,
			EntityPlayer player) {
		TileEntityCanvas canvas = (TileEntityCanvas) world.getTileEntity(pos);
		ItemStack stack = new ItemStack(ModBlocks.canvas);
		NBTTagCompound nbt = new NBTTagCompound();
		if(canvas != null) 
			nbt.setInteger("colour", canvas.getColour());
		else
			nbt.setInteger("colour", 0xFFFFFF);
		stack.setTagCompound(nbt);
		return stack;
	}
	
	/**
	 * Needed to make sure our block is rendered correctly
	 */
	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	/**
	 * Create the tile entity
	 */
	@Override
	public TileEntity createTileEntity(World world, IBlockState state) {
		return new TileEntityCanvas();
	}
	
	/**
	 * Also create the tile entity
	 */
	@Override
	public TileEntity createNewTileEntity(World world, int meta) {
		return new TileEntityCanvas();
	}
	
	/**
	 * When placed it will update the colour to that of the tile entity which the tile entity inherits from the item block
	 */
	@Override
	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer,
			ItemStack stack) {
		if(!world.isRemote) {
			TileEntityCanvas canvas = (TileEntityCanvas) world.getTileEntity(pos);
			if(canvas != null && stack.hasTagCompound() && stack.getTagCompound().hasKey("colour"))
				canvas.setColour(stack.getTagCompound().getInteger("colour"));
		}
		world.markBlockRangeForRenderUpdate(pos, pos); //Update the blocks render
	}
	
	/**
	 * Not fully functioning. Works with <code> /setblock <x> <y> <z> air 0 destroy </code> but not when breaking normally with your hand
	 */
	@Override
	public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) {
		List<ItemStack> drops = new ArrayList<ItemStack>();
		TileEntityCanvas canvas = (TileEntityCanvas) world.getTileEntity(pos);
		ItemStack stack = new ItemStack(ModBlocks.canvas);
		NBTTagCompound nbt = new NBTTagCompound();
		if(canvas != null) //When you break it with a command
			nbt.setInteger("colour", canvas.getColour());
		else //When you break it with your hand
			nbt.setInteger("colour", 0xFFFFFF);
		stack.setTagCompound(nbt);
		drops.add(stack);
		return drops;
	}
	
	@Override
	public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te,
			ItemStack stack) {
		if(!world.isRemote)
			BitOfEverything.network.sendToServer(new CanvasItemDropMessage(pos));
	}

}

The Tile Entity:

package cjminecraft.bitofeverything.tileentity;

import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

/**
 * The canvas tile entity which stores the blocks colour
 * @author CJMinecraft
 *
 */
public class TileEntityCanvas extends TileEntity {
	
	//The colour as an int
	private int colour;
	
	/**
	 * Initialise the colour to be white
	 */
	public TileEntityCanvas() {
		this.colour = 0xFFFFFF;
	}
	
	/**
	 * Read the colour from NBT data
	 */
	@Override
	public void readFromNBT(NBTTagCompound nbt) {
		super.readFromNBT(nbt);
		this.colour = nbt.getInteger("colour");
	}
	
	/**
	 * Write the correct NBT data
	 */
	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
		nbt.setInteger("colour", this.colour);
		return super.writeToNBT(nbt);
	}
	
	/**
	 * Get the colour of the canvas
	 * @return The colour of the canvas
	 */
	public int getColour() {
		return colour;
	}
	
	/**
	 * Set the colour of the canvas
	 * @param colour The new colour of the canvas
	 */
	public void setColour(int colour) {
		this.colour = colour;
	}
	
	/**
	 * The packet which is used to update the tile entity which holds all of the
	 * tileentities data
	 */
	@Override
	public SPacketUpdateTileEntity getUpdatePacket() {
		NBTTagCompound nbt = new NBTTagCompound();
		this.writeToNBT(nbt);
		int metadata = getBlockMetadata();
		return new SPacketUpdateTileEntity(this.pos, metadata, nbt);
	}

	/**
	 * Reads the nbt when it receives a packet
	 */
	@Override
	public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
		this.readFromNBT(pkt.getNbtCompound());
	}

	/**
	 * Gets the nbt for a new packet
	 */
	@Override
	public NBTTagCompound getUpdateTag() {
		NBTTagCompound nbt = new NBTTagCompound();
		this.writeToNBT(nbt);
		return nbt;
	}

	/**
	 * Handles when you get an update
	 */
	@Override
	public void handleUpdateTag(NBTTagCompound tag) {
		this.readFromNBT(tag);
	}

	/**
	 * Gets the tile entities nbt with all of the data stored in it
	 */
	@Override
	public NBTTagCompound getTileData() {
		NBTTagCompound nbt = new NBTTagCompound();
		this.writeToNBT(nbt);
		return nbt;
	}

}

Registration of the packet: (called in pre init in the common proxy)

BitOfEverything.network.registerMessage(CanvasItemDropMessageHandler.class, CanvasItemDropMessage.class, Reference.PACKET_ID_CANVAS, Side.SERVER);

 

All help is greatly appreciated. I hope someone will be able to help me figure this out!

Posted

You shouldn't need a packet to do this. getDrops is called after the Block has been removed, which means the TileEntity has also already been removed so you can't get the colour information there. Instead you can override harvestBlock and use the TileEntity parameter (which should be an instance of your TE) to get the colour and spawn the drops yourself.

Posted (edited)

Just tried that with this code:

	@Override
	public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te,
			ItemStack stack) {
		TileEntityCanvas canvas = (TileEntityCanvas) te;
		ItemStack itemstack = new ItemStack(ModBlocks.canvas);
		NBTTagCompound nbt = new NBTTagCompound();
		if(canvas != null)
			nbt.setInteger("colour", canvas.getColour());
		else
			nbt.setInteger("colour", 0xFFFFFF);
		stack.setTagCompound(nbt);
		spawnAsEntity(world, pos, itemstack);
	}

Still doesn't work. It leaves it with the white colour while the block I am breaking is orange in the tile entity

Edited by CJMinecraft
Posted

Thanks. That fixed the block drop. Unfortunately when I place the coloured block the tile entity receives the colour correctly. The particles of the block are coloured correctly but the actual block remain white until another canvas block is placed.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.