Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

1.14.4 What does the discriminator byte do in PacketBuffers?


Keheck
 Share

Recommended Posts

I am currently setting up some networking to synchronize data between Clients and Servers, and I've been running into a problem where I got an invalid discriminator byte on my channel.

I've fixed that by "shifting" the data written to the PacketBuffer in my encoding method by one byte.

To know what exactly what I'm talking about, you can take a look at this and that class, they contain the important stuff (Mod's main class and the Message class, respectively). The packet is sent off here . (An Item class' onItemRightClick method)

 

Or you can open the spoiler:

 
 
 
 
 
 
 
 
Spoiler

In the mod's main class (io.github.kehek.mobfighters.Mobfighters)


private static int MSG_ID = 0;
// CHANNEL is a SimpleChannel instance named "mobfighters:main" and a simple version cheking of "1".equals("1") and a Supplier<String> returning "1"
public void doCommonSetup(FMLCommonSetupEvent event)
{                               //Originally MSG_ID++, doesn't change the outcome in any notable ways though
    MobfightersNetworkHandler.CHANNEL.registerMessage(++MSG_ID, FightStartPacket.class, FightStartPacket::encode, FightStartPacket::decode, FightStartPacket::handle);
}

In the message class (io.github.keheck.mobfighters.util.network.FightStartPacket)


// Offset the data by one byte, to get a valid discriminator at index 0
// Was previously not present, and caused invalid discriminator problems
private static final int off = 1;
public static void encode(FightStartPacket packet, PacketBuffer buffer)
{
    for(int i = 0; i < 4; i++)
    {
        // Put the least significant bits in the buffer
        boolean putLeast = i%2 == 0;

        // Put the player in the buffer
        if(i < 2)
        {
            if(putLeast)
                buffer.setLong(i*Long.BYTES+off, packet.playerUUID.getLeastSignificantBits());
            else
                buffer.setLong(i*Long.BYTES+off, packet.playerUUID.getMostSignificantBits());
        }
        // Put the enemy in the buffer
        else
        {
            if(putLeast)
                buffer.setLong(i*Long.BYTES+off, packet.enemyUUID.getLeastSignificantBits());
            else
                buffer.setLong(i*Long.BYTES+off, packet.enemyUUID.getMostSignificantBits());
        }
    }
    buffer.setInt(Long.BYTES*4+off, packet.fightID);
    buffer.setBoolean(Long.BYTES*4 + Integer.BYTES+off, packet.enemyWild);
}

In the item's class (io.github.keheck.mobfighters.item.FightInitiatorItem)


@Override
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn)
{
    // Disclaimer: Simplified for readability
    if(!worldIn.isRemote())
    {
        ServerPlayerEntity serverPlayer = (ServerPlayerEntity)playerIn;

        // I know, there are convenience-methods for sending packets to clients.
        MobfightersNetworkHandler.CHANNEL.sendTo
                (
                        new FightStartPacket(1, playerIn, playerIn),
                        serverPlayer.connection.getNetworkManager(),
                        NetworkDirection.PLAY_TO_CLIENT
                );
    }

    return super.onItemRightClick(worldIn, playerIn, handIn);
}

 

 

It seems like the discriminator is somehow tied to the id of the Message registered on the channel but I would like some confirmation/correction on that theory.

What is the discriminator actually used for?

Link to comment
Share on other sites

2 minutes ago, Keheck said:

It seems like the discriminator is somehow tied to the id of the Message registered on the channel but I would like some confirmation/correction on that theory.

It's not tied to it. It is it.

 

Do not use the set methods on PacketBuffer. Use writeXXX to write and readXXX to read. Both must be done in the same order and you must write and read exactly the same data.

Link to comment
Share on other sites

So if I understood correctly, the first byte of a packet payload is always(?) the id of the message in the specific channel. It is to correctly identify the message that the payload needs to be decoded into, since there is no (more efficient) way to store the message type itself into the payload, correct?

Link to comment
Share on other sites

9 minutes ago, Keheck said:

So if I understood correctly, the first byte of a packet payload is always(?) the id of the message in the specific channel.

If you use SimpleChannel, yes. You can also do completely custom packets by using newEventChannel.

 

10 minutes ago, Keheck said:

It is to correctly identify the message that the payload needs to be decoded into, since there is no (more efficient) way to store the message type itself into the payload, correct?

It's how SimpleChannel is implemented. It gives every message an ID and sends that ID as the first byte, so that the receiver knows which message type it is. You could use newEventChannel and write your own implementation, if you need it.

Link to comment
Share on other sites

3 minutes ago, diesieben07 said:

You could use newEventChannel and write your own implementation, if you need it.

When would it be better to use that instead of a SimpleChannel? Like, what are some example cases you could name?

Link to comment
Share on other sites

Just now, Keheck said:

When would it be better to use that instead of a SimpleChannel? Like, what are some example cases you could name?

I have never used it. You would need to use it if you had more than 256 different packets (you would run out of IDs with SimpleChannel then). It can also be useful when communicating with a plugin on a non-forge server (Sponge or Bukkit), which don't have the SimpleChannel implementation and might use a custom encoding.

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
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.

 Share



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.