MaterialData alternative

Discussion in 'Plugin Development' started by EvilWitchdoctor, Dec 12, 2023.

  1. Offline

    EvilWitchdoctor

    So (quite) a few years ago the MaterialData class became deprecated, with a message telling us to use BlockData instead.

    However, I still find myself using MaterialData nearly everywhere, and can't seem to find alternatives for a few very common usages, so I thought I'd ask generally here, with some examples below.

    Case 1:
    We have an ItemStack object, and want to check some property, like "is it a pressure plate?"
    Approach 1:
    Code:
    Material type = item.getType();
    return type.name().endsWith("_PRESSURE_PLATE");
    Approach 2:
    Code:
    switch(type){case OAK_PRESSURE_PLATE: case CHERRY_PRESSURE_PLATE: ... return true;}
    Approach 3:
    Code:
    @SuppressWarnings("deprecation")
    return org.bukkit.material.PressurePlate.class.isAssignableFrom(type.getData());
    The 1st approach is simple and works for a lot of properties, e.g. "is this a sword", "is this a shulker_box", "is this a sign", however it becomes a lot messier for queries like "is this a double-tall plant". Also, I'm not sure about the performance of doing lots String comparisons, vs. an Enum-switch or type check, and more generally it feels prone to breaking if material(s) with a similar name but different properties get added in a future version.

    The 2nd approach has the best performance, but is the most prone to breaking when Minecraft updates, since the plugin developer will need to constantly update the switch cases with new items. It can also get quite verbose - checking "is this item colorable" requires a HUGE switch statement.

    The 3rd approach is consistently the cleanest... but it is Deprecated. As far as I can tell, there is no way to fetch a BlockData from an ItemStack, so we can only use the deprecated MaterialData class from item.getData().


    This has been bugging me for several years so I'd be really glad to learn if there is some clean solution I've missed (Google search results seem to just lead to Spigot forums posts where they recommend NMS... lol)
     
  2. Offline

    EvilWitchdoctor

  3. Offline

    KarimAKL

    @EvilWitchdoctor You should probably use BlockData. There are quite a few implementations for different blocks. You could check if a block is Ageable, Powerable, a TrapDoor, a Sign, etc.

    Regarding your example:
    According to the CraftBukkit source code, there are two implementations of the pressure plate: CraftPressurePlateBinary and CraftPressurePlateWeighted. Unfortunately, none of these have a dedicated API version as they both simply inherit from CraftBlockData. You could, however, check the implementation name. Something like this should work:
    Code:Java
    1. Material material = /* your Material */;
    2. BlockData data = material.createBlockData();
    3.  
    4. // Avoid referencing the version-dependent class
    5. String name = data.getClass().getSimpleName();
    6. if (name.equals("CraftPressurePlateBinary") || name.equals("CraftPressurePlateWeighted")) {
    7. // Block is a pressure plate
    8. } else {
    9. // Block is not a pressure plate
    10. }

    Of course, this is similar to your first approach, where you compare two strings. The difference here is that you won't have to rely on the material name being consistent.

    Edit: I completely missed the point of the thread. Sorry about that. You can, however, still use BlockData with Material. I have edited my post to use that.
     
    Last edited: Jan 13, 2024
  4. Offline

    EvilWitchdoctor

    Thanks for the reply, and no worries!
    This is clever approach for certain cases like the one you showed, I'll keep it in my toolbox for sure - it's a nice way to match for Material types that have different names but inherit the same class.
     
    KarimAKL likes this.

Share This Page