Jump to content

[1.12] Sending a packet from the server to the client


acadus

Recommended Posts

I'm trying to make it so that when a player right clicks on a block, it opens a GUI (no inventory) for them, but the packet I am using gives a NullPointerException when I try and send the packet. The error only highlights the line in the block activation code and does not say what variable is null, presumably due to the threading process. Here is my code:

 

Packet & Handler

public class PacketOpenGui implements IMessage
{
	public PacketOpenGui(int guiid, BlockPos pos)
	{
		this.guiID = guiid;
		this.blockPos = pos;
	}
	
	private int guiID;
	private BlockPos blockPos;

	@Override
	public void fromBytes(ByteBuf buf) 
	{
		guiID = buf.readInt();
		blockPos = BlockPos.fromLong(buf.readLong());
	}

	@Override
	public void toBytes(ByteBuf buf) 
	{
		buf.writeInt(guiID);
		buf.writeLong(blockPos.toLong());
	}
	
	public static class Handler implements IMessageHandler<PacketOpenGui, IMessage> 
	{
		
        @Override
        public IMessage onMessage(PacketOpenGui message, MessageContext ctx) {
            FMLCommonHandler.instance().getWorldThread(ctx.netHandler).addScheduledTask(() -> handle(message, ctx));
            return null;
        }

        private void handle(PacketOpenGui message, MessageContext ctx) 
        {
        	if(message.guiID == 0)
        	{
        		ModTest.proxy.openGui(new GuiExample(new V3(message.blockPos.getX(), message.blockPos.getY(), message.blockPos.getZ()), "-x", null, (EntityPlayer)ctx.getServerHandler().player));
        	}
        }
	}
}

 

Packet Registry

public class PacketHandler 
{
	 private static int packetId = 0;

	    public static SimpleNetworkWrapper INSTANCE = null;

	    public PacketHandler() {
	    }

	    public static int nextID() {
	        return packetId++;
	    }

	    public static void registerMessages(String channelName) {
	        INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(channelName);
	        registerMessages();
	    }

	    public static void registerMessages() {
	        INSTANCE.registerMessage(PacketOpenGui.Handler.class, PacketOpenGui.class, nextID(), Side.SERVER);
	    }
}

 

Client Proxy Exert

public class ClientProxy extends CommonProxy {
	@Override //Override from empty function in CommonProxy
	public void openGui(@Nullable GuiScreen gui)
	{
		Minecraft.getMinecraft().displayGuiScreen(gui);
	}
}

 

Block Activation

@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        if (!worldIn.isRemote)
        {
        	PacketHandler.INSTANCE.sendTo(new PacketOpenGui(0, pos), (EntityPlayerMP)playerIn); //Error occurs on this line without any explanation
        }

        return true;
    }

 

Link to comment
Share on other sites

The Side parameter is which side is the receiver.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

15 hours ago, Draco18s said:

The Side parameter is which side is the receiver.

Ah sorry, my bad.

 

I corrected it but the error still persists. Is there any way I can get more information on the error so that you can better help me?

Link to comment
Share on other sites

18 minutes ago, diesieben07 said:
  • Your IMessage class needs a no-argument constructor.
  • Putting openGui in your proxy like that doesn't help. You are still creating the GuiScreen itself outside of the client proxy in common code. This will crash a server. 
  • You never change this to any other value.

Okay, I've removed the constructor arguments and moved the creation of the GuiScreen instance into the client proxy. I have actually registered the instance in the preInit of my common proxy which is then called in the mod file proxy, but I forgot to include this in the original post. However, the same NullPointerException keeps occuring at the same line in the Block Activation. Here are the updated classes:

 

Packet and Handler

public class PacketOpenGui implements IMessage
{
	public PacketOpenGui()
	{}
	
	private BlockPos blockPos;

	@Override
	public void fromBytes(ByteBuf buf) 
	{
		blockPos = BlockPos.fromLong(buf.readLong());
	}

	@Override
	public void toBytes(ByteBuf buf) 
	{
		buf.writeLong(blockPos.toLong());
	}
	
	public static class Handler implements IMessageHandler<PacketOpenGui, IMessage> 
	{
		
        @Override
        public IMessage onMessage(PacketOpenGui message, MessageContext ctx) {
        	try{
            FMLCommonHandler.instance().getWorldThread(ctx.netHandler).addScheduledTask(() -> handle(message, ctx));
        	}
        	catch(Exception e)
        	{
        		e.printStackTrace();
        	}
            return null;
        }

        private void handle(PacketOpenGui message, MessageContext ctx) 
        {
        		ModTest.proxy.openGui();
        }
	}
}

 

Packet Registry

public class PacketHandler 
{
	 private static int packetId = 0;

	    public static SimpleNetworkWrapper INSTANCE = null;

	    public PacketHandler() {
	    }

	    public static int nextID() {
	        return packetId++;
	    }

	    public static void registerMessages(String channelName) {
	        INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(channelName); //Called in common proxy
	        registerMessages();
	    }

	    public static void registerMessages() {
	        INSTANCE.registerMessage(PacketOpenGui.Handler.class, PacketOpenGui.class, nextID(), Side.CLIENT);
	    }
}

 

Client Proxy Exert

@Override
	public void openGui()
	{
		Minecraft.getMinecraft().displayGuiScreen(new GuiExample(new V3(1,1,1), "-x", null, (EntityPlayer)Minecraft.getMinecraft().player));
	}

 

Block Activation

@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        if (!worldIn.isRemote)
        {
        	PacketHandler.INSTANCE.sendTo(new PacketOpenGui(), (EntityPlayerMP)playerIn);
        }

        return true;
    }

 

Edit: I just removed the use of blockPos for the time being to make things simpler.

Edited by acadus
Link to comment
Share on other sites

19 minutes ago, diesieben07 said:

You can keep them. You just need to also have a no-argument constructor.

 

  • Code style, issue 1.
  • Please clarify what a "mod file proxy" is.
  • Show your main mod class and proxies.

 

Common Proxy:

@Mod.EventBusSubscriber
public class CommonProxy 
{
	public void registerItemRenderer(Item item, int meta, String id) {

	}

	public String localize(String unlocalized, Object... args) {
		return I18n.translateToLocalFormatted(unlocalized, args);
	}

	public void registerRenderers() {
	}
    
	public void preInit(FMLPreInitializationEvent e) 
	{
		 PacketHandler.registerMessages("packettests");
    }
	
	public void init(FMLInitializationEvent e) 
	{
		
    }
	
	public void postInit(FMLPostInitializationEvent e) 
	{
		
    }
    
	public void openGui()
	{
		
	}
	
}

 

Client Proxy:

@Mod.EventBusSubscriber(Side.CLIENT)
public class ClientProxy extends CommonProxy {
	
	@Override
	public void registerItemRenderer(Item item, int meta, String id) {
		ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(ModTest.MODID + ":" + id, "inventory"));
	}

	@Override
	public String localize(String unlocalized, Object... args) {
		return I18n.format(unlocalized, args);
	}

	@Override
	public void registerRenderers() {
	}
	
	@Override
    public void preInit(FMLPreInitializationEvent e) 
	{
		
    }
	
	@Override
    public void init(FMLInitializationEvent e) 
	{
        
    }
	
	@Override
    public void postInit(FMLPostInitializationEvent e) 
	{
        
    }
	
	@Override
	public void openGui()
	{
		Minecraft.getMinecraft().displayGuiScreen(new GuiExample(new V3(1,1,1), "-x", null, (EntityPlayer)Minecraft.getMinecraft().player));
	}
	
}

 

Mod File:

@Mod(modid = ModTest.MODID, name = ModTest.MODNAME, version = ModTest.VERISON, useMetadata = true)
public class ModTest {

	public static final String MODID = "modtest";
	public static final String MODNAME = "Mod Test";
	public static final String VERISON = "1.0.0";
	
	@SidedProxy(clientSide = "acadus.modtest.proxy.ClientProxy", serverSide = "acadus.modtest.proxy.ServerProxy")
	public static CommonProxy proxy;
	
	@Mod.Instance
	public static ModTest instance;
	
	public static Logger log;
	
	@Mod.EventHandler
	public void preInit(FMLPreInitializationEvent event)
	{
		log = event.getModLog();
		proxy.preInit(event);
	}
	
	@Mod.EventHandler
	public void init(FMLInitializationEvent event)
	{
		proxy.init(event);
	}
	
	@Mod.EventHandler
	public void postInit(FMLPostInitializationEvent event)
	{
		proxy.postInit(event);
	}
	
	@Mod.EventBusSubscriber
	public static class RegsitrationHandler {

		@SubscribeEvent
		public static void registerItems(RegistryEvent.Register<Item> event) {
			//ModItems.register(event.getRegistry());
			ModBlocks.registerItemBlocks(event.getRegistry());
		}

		@SubscribeEvent
		public static void registerBlocks(RegistryEvent.Register<Block> event) {
			ModBlocks.register(event.getRegistry());
		}

		@SubscribeEvent
		public static void registerModels(ModelRegistryEvent event) {
			//ModItems.registerModels();
			ModBlocks.registerModels();
		}

	}
	
}

 

Link to comment
Share on other sites

23 minutes ago, diesieben07 said:

Your client proxy overrides preInit to do nothing, so the packet handler is not initialized.

Why do you have a "common proxy"? This code should go in your main mod class.

Ah, of course, I can't believe I overlooked it.

 

Should I create an instance for my client and server proxy in the mod file and then remove the common proxy?

Link to comment
Share on other sites

2 minutes ago, diesieben07 said:

No. What you now have as "common proxy" should be an interface simply called "proxy". It should not contain any code and simply act as the interface (duh) to the client and server proxy implementation.

Got it, thank you very much :)

Link to comment
Share on other sites

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.