ProtocolLib

3M Downloads

API representation for packet fields of type BlockEntityType

blablubbabc opened this issue ยท 3 comments

commented

For example, in MC 1.18.x, the TILE_ENTITY_DATA packet (ClientboundBlockEntityDataPacket) stores a field of type BlockEntityType. I am not sure how I can analyze this field via ProtocolLib, for example to conditionally only modify packets that affect a specific type of tile entity.

Possible solutions I can think of:

  • Add a new converter to BukkitConverters that converts objects of type BlockEntityType to something NMS-unspecific, such as: The corresponding Bukkit BlockState class, ProtocolLib's MinecraftKey, Bukkit's NamespacedKey, the String key, ..
  • Expose a wrapper for Minecraft's BlockEntityType registry in WrappedRegistry. This would then allow the lookup of the key for a given BlockEntityType instance.
commented

See #1469 - you can use container.getStructures().read(0) for this.

commented

See #1469 - you can use container.getStructures().read(0) for this.

I am not sure how I would use that to for example check whether the BlockEntityType is minecraft:sign. As far as I can tell, these ids are not actually stored by the BlockEntityType instance itself, but only by the registry they are stored in.
I could maybe inspect the com.mojang.datafixers.types.Type stored by the BlockEntityType instance to derive whether it is a particular BlockEntityType. I have not tried that yet. But even if this datafixer type happens to store the id, it seems like quite an involved/non-ideal workaround to use that for identification purposes.

commented

Hi,

I hade the same issue. Using some reflection I was able to build a work around. I made use of the namespaced key representation of the TileEntityTypes.

import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.AbstractWrapper;
import com.comphenix.protocol.wrappers.MinecraftKey;

/**
 * @see net.minecraft.world.level.block.entity.TileEntityTypes<T>
 * @author Kaonashi97
 */
public class WrappedTileEntityType extends AbstractWrapper {

    public static final MinecraftKey SIGN = new MinecraftKey("sign");
    public static final MinecraftKey CAMPFIRE = new MinecraftKey("campfire");
    public static final MinecraftKey SKULL = new MinecraftKey("skull");
    public static final MinecraftKey BEACON = new MinecraftKey("beacon");
    public static final MinecraftKey MOB_SPAWNER = new MinecraftKey("mob_spawner");

    private static final String WRAPPED_CLASS_NAME = "world.level.block.entity.TileEntityTypes";
    private static final String WRAPPED_CLASS_PATH = WRAPPED_CLASS_NAME;

    private static final Class<?> WRAPPED_CLASS = MinecraftReflection.getMinecraftClass(WRAPPED_CLASS_PATH);

    private static final MethodAccessor GET_NAMESPACED_KEY = Accessors.getMethodAccessor(WRAPPED_CLASS, "a", WRAPPED_CLASS);

    private WrappedTileEntityType(Object handle) {
        super(WRAPPED_CLASS);
        setHandle(handle);
    }

    public static WrappedTileEntityType fromHandle(Object handle) {
        return new WrappedTileEntityType(handle);
    }

    public MinecraftKey getKey() {
        return MinecraftKey.fromHandle(GET_NAMESPACED_KEY.invoke(null, this.handle));
    }
}

On the using side, if you get the handle for the TileEntityType from your Packet, you can use WrappedTileEntityType.fromHandle(Object). Compare the return value of getKey() with the constants provided in the class: WrappedTileEntityType.SIGN.getFullKey().equals(tileEntityType.getKey().getFullKey())

This worked for me as I just needed some of them. This is probably not fail safe but maybe a good start.