API representation for packet fields of type BlockEntityType
blablubbabc opened this issue ยท 3 comments
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.
See #1469 - you can use container.getStructures().read(0)
for this.
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.
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.