ProtocolLib

3M Downloads

How can I edit the MetaData of an outgoing spawn entity packet?

Loudbooks opened this issue · 14 comments

commented

Make sure you're doing the following

  • You're using the latest build for your server version
  • This isn't an issue caused by another plugin
  • You've checked for duplicate issues
  • You didn't use /reload

Describe the question
A clear and concise description of what your question is.
So I'm trying to make an entity packet to show to one player. I am able to get the entity to show, but I'm having difficulty changing the MetaData of the entity. I know I have to use the DataWatcher, but I have no idea how to use this. I can't find any up-to-date information online. Can anyone help? This is my spawn entity code:

        Player p = (Player) sender;
        Location location = p.getLocation();
        PacketContainer packet = manager.createPacket(PacketType.Play.Server.SPAWN_ENTITY);
        packet.getIntegers().write(0, 1000);
        packet.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND);
        packet.getUUIDs().write(0, UUID.randomUUID());
        packet.getDoubles().write(0, 170.0);
        packet.getDoubles().write(1, 113.0);
        packet.getDoubles().write(2, 69.0);

        PacketContainer packet1 = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
        WrappedDataWatcher watcher = new WrappedDataWatcher();
        byte t = (byte) 0x20;
        watcher.setObject(t, (byte) 0x20);
        int id = 1000;
        WrapperPlayServerEntityMetadata metadataPacket = new WrapperPlayServerEntityMetadata();
        metadataPacket.setEntityID(id);
        metadataPacket.setMetadata(watcher.getWatchableObjects());
        metadataPacket.sendPacket(p);

        try {
            manager.sendServerPacket(p, packet);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


        return true;

This code spawns the entity but doesn't apply any MetaData.

TLDR: How do I update the metadata of an outgoing Spawn Entity Packet?

API method(s) used
Protocol Lib
Protocol Lib Wrapper

Thanks so much!

commented

Don't use PacketWrapper - it is outdated. Just construct a metadata packet, write the entity id and meta objects and send it.

commented

@derklaro

Is there a reference for object IDs? How am I supposed to know which is which?

Extra Note: When I set an Entity ID when sending a packet if I use that entity ID somewhere else, will it target that entity?

commented

@derklaro

Thanks a lot!
Last question: How do I specify an Entity ID? It doesn't look like a type on the Entity base class.
This is my code right now:
image
image

commented

First of all, you are writing to the wrong packet container. The entity id is just an int in the packet.

commented

@derklaro

How do you edit and create the WatchableCollection object?
image
It wants a list?? I'm confused :(

commented

@derklaro

Wow, I really have no idea what I'm doing. What is the correct packet container type?
image

commented

No, the type was correct but you used the wrong container field :) (packet instead of metaData)

commented

@derklaro

Oh yea, I saw that lol.

Im still getting the error when I change it to metaData though.

03.04 16:17:59 [Server] INFO Caused by: com.comphenix.protocol.reflect.FieldAccessException: No field with type byte exists in class PacketPlayOutEntityMetadata.

commented

The packet contains 2 fields: the entity id (integer) and the data watcher objects (watchableCollection) - just modify these

commented

Great! It worked! Now how would it be different for let's say a custom name? What's the pattern here?

commented

Just create one then I guess 🤔

commented

@derklaro

I'm getting somehwhere:

        List<WrappedWatchableObject> list = new ArrayList<>();
        WrappedWatchableObject object = new WrappedWatchableObject(0, (byte) 0x20);
        list.add(object);
        metaData.getWatchableCollectionModifier().write(0, list);
        metaData.getIntegers().write(0, 1000);

image

commented

You need to add a serializer for the type. In your case use new WrappedWatchableObject(new WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20)