Resource XSeries - XMaterial, XSound, XPotion, XEnchantment, Titles, ActionBar, etc

Discussion in 'Spigot Plugin Development' started by CryptoMorin, Jun 16, 2019.


Do you need XParticle? (Read the first post for more info)

  1. Yes

  2. No

  1. XSound, XEnchantment, XPotion, XBlock, ActionBar and Titles are here! (Check the main post)
    I'm still working on XParticle.
    Changed the GitHub name to XSeries

    This version is strictly focused to provide maximum (possible) performance. Analyzed bit by bit, electron by electron.
    I guess we can consider it as a thank you gift to bees that fixed the 1.14 performance tragedy using Symmetric Quantum Superpositional Qubit algorithm?
    In all seriousness, the performance is much better. But no, it's not that crazy. I didn't read intel architecture manual for nano optimizations.
    Some premature optimization? Yes. Let's not talk about it.

    You might have to change a few things in your code. Please read the changelog, at least the Added & Fixed part.
    The main post is also updated. You might want to read that as well.

    Added & Fixed:
    • Added 1.15 support.
    • Added setType(ItemStack). Use parseItem() instead where possible.
    • Added local isOneOf(List<String> materials). It's a really great method if you're checking a material list from your config.
    • All the matchXMaterial methods are now wrapped in an Optional object.
    • For those who don't know how to use it. Do not use orElse(null) to do if (obj == null) use Optional#isPresent() & Optional#get() instead.
    • MinecraftVersion enum will now have "V" prefix instead of "VERSION" as it makes it unnecessarily long.
    • VALUES field is now an immutable list. Please avoid using XMaterial.values() for the sake of performance.
    • Fixed some kind of hidden recursion with isDuplicated(String name) throwing StackOverFlow errors for matchXMaterial() and even when it worked, it was a complete disaster.
    • Fixed an issue with andesite, granite and diorite compatibility.
    • Overriding toString()... In most cases you should be using name() instead anyway.
    • Removed local toWord(), use toString() instead.
    • Removed RegEx \d+ replace from format() method as it's not compatible with music discs.
    • Removed isVersionOrHigher(String version) Use isVersionOrHigher(MinecraftVersion version) instead.
    • Removed parseMaterial(String name, byte data). The data is ignored when parsing the material, so I don't even know why this was a thing.
    • Removed suggestOldMaterialIfNew() use parseMaterial(true) instead.
    • Replaced getVersionIfNew() with getMaterialVersion()

    • Replaced most of the Java 8 streams with good old for-each loops. They're indeed faster (for our case)
    • Using Guava Cache for caching both material strings and parsed materials.
    • Replaced all strings with characters where possible.
    • Material name formatter is now much faster with Apache's StringUtils and pre-compiled patterns.
    • isSupported() method will now do more basic checks before doing complex checks.
    • Removed MINECRAFT: replace check from format() method. It rarely happens and is useless.
    • Replaced \s+ RegEx replace with a normal whitespace string replace in format() method as \W+ will already take care of it.
    • Sorted request order in format() method for optimal performance.
    • Damageable list is now an immutable set.
    • Duplicated list is now an immutable map.
    • Removed Pattern.quote() and escaped the character manually (for version checks) as that method runs a bunch of extra checks.
    • Reduced null checks and format() calls where possible.
    • isVersionOrHigher(version) uses a simple ordinal number check.
    • Other micro/nano-optimizations in different methods that no one cares about.
    • Note: We can't use a static map for matchXMaterial lookup as it's not compatible with XMaterial Paradox (Duplication Check)
    • Also, data values can't be used anymore if we do that. While we can do more optimizations, we have to consider the memory as well.

    • Cleaned exceptions.
    • Cleaned JavaDocs. It's all complete now.
    • The MIT License looks cleaner now I guess...?
    • Cleaned the enum format and sorted alphabetically.
    • I was planning to use IntelliJ's annotations, or even better checker framework annotaions. But some people are still using Eclipse. It all now uses JavaX
    • Note: The order of MinecraftVersion enum should not be changed. Please change your settings if your IDE auto sorts enums.
    #121 CryptoMorin, Dec 11, 2019
    Last edited: Dec 11, 2019
    • Like Like x 3
  2. Thanks so much for the update! I wasn't expecting it this soon!
  3. What a fucking legend.
    Thank you so much for doing this
    • Agree Agree x 1
  4. Submitted a pull request with some improvements.
    • Winner Winner x 1
  5. Merged, thanks.

    • Refactored ImmutableMap to ImmutableEnumMap for performance improvements
    • Used stream method reference over direct method invocation
    • Replaced string utility implementation with one provided by a Spigot lib
    • Removed condition redundancy
  6. So with the removal of the parseMaterial, what is the new proper way to get the ItemStack of a matched material? Is it XMaterial.matchXMaterial(material).get().parseMaterial())?
  7. The proper way of getting an ItemStack isn't even parseMaterial() you should be using parseItem() instead.
    It depends on what the material argument is. In most cases, it's a String, so let's go with that.
    If it's not a String then it doesn't return an Optional. You can just skip the isPresent check.

    Code (Java):
    Optional<XMaterial> mat = XMaterial.matchXMaterial("BEEHIVE");

    // Do not use .orElse(null)
    // Returns false if the material doesn't exist. It will return true even if the material isn't supported in the current version.
    if (!mat.isPresent()) return;
    // If you want suggestions for older versions use .parseItem(true) but there isn't any suggested material for bee hive rn.
    ItemStack hive = mat.get().parseItem();

    // If you already know the material is going to be BEEHIVE just use it directly.
    #127 CryptoMorin, Dec 13, 2019
    Last edited: Dec 13, 2019
    • Useful Useful x 1
  8. MeliodasX

    MeliodasX Previously Shin1gamiX

    Items such as ROSE_RED and several other ink related items do not properly work on 1.8.8 (only tested in that version). It throws an NPE when attempting to get it's material, not entirely sure what's wrong. @CryptoMorin can you please take a look at this issue?
    • Agree Agree x 1
  9. Thanks for the response! I'll start using parseItem instead. I do use strings for the input to get the material currently.
  10. Can I see your code for that part? And the stack trace.
    Also make sure you're using the latest one. Someone made a PR a few days ago.
    #130 CryptoMorin, Dec 14, 2019
    Last edited: Dec 14, 2019
  11. Minor Improvements to all utils:
    • Changed from ImmutableList to EnumSet
    • toString now calls capitalize instead of capitalizeFully from Apache.
    • Removed some project structures.
    If you're having problems with the nullability annotations using maven, you can import the following dependency:
    Code (Text):
    Or you can just remove them with a quick Ctrl+R it's for JavaDoc purposes only.
  12. Is there not way to parse material and still have the correct material? What I mean by this is if I use parseItem() the glass, for example, has the correct colour. When I use parseMaterial() on the other hand, it returns a while glass always. Is there a way to get around this? I'm doing Block#setType()
  13. MeliodasX

    MeliodasX Previously Shin1gamiX

    If you're on versions prior to 1.13 then obviously no. Versions prior to that do not use material names but rather durabilities for the coloring and different material of some type. If what you're doing is block related, take a look at XBlock. XMaterial is purely itemstack related.
  14. Oh I didn't know that was a thing ,thanks <3
  15. Code (Java):
    Block block = player.getLocation().getBlock().getRelative(x, y, z);
                            XBlock.setType(block, XMaterial.RED_STAINED_GLASS);
    What did I do wrong?

    Edit: Just saw it's a TODO. What should I do instead?
  16. kinda curious, whats the issue with declaring everything along the lines of this:
    Code (Java):
    public class XMaterial {

        public static final Material GLASS = Material.whatevertherealnameforglassis;
        public static final Material FISH_BUCKET = ver == 1.8 ? Material.WATER_BUCKET : Material.FISH_BUCKET; // psuedo code, gettin lazy
     /e public static final Material FISH_BUCKET = ver == 1.8 ? Material.WATER_BUCKET : Material.valueOf("FISH_BUCKET"); // incase java says no to the nonexistent enum

        static {
            // for declaring any of the complex ones

    mm guess it depends on how java handles enums that dont exist. could just rewrite it to be slightly heavier when it loads but after that its good, instead of Material.WATER_BUCKET just Material.valueOf("WATER_BUCKET"). same with the rest of em

    heck, a bit cheap but:
    Code (Java):
    public static Material findProperMaterial(String... names) {
        for(String name : names) {
            try {
                return Material.valueOf(name);
            } catch(Exception e) {}

    public static final Material FISH_BUCKET = findProperMaterial("FISH_BUCKET", "WATER_BUCKET");
    wouldn't even need a version api
    #136 Warren1001, Dec 21, 2019
    Last edited: Dec 21, 2019
    • Agree Agree x 1
  17. Awesome project, thank you <3
  18. XBlock:
    • Fixed an issue with setColor method.
    • Added unsupported exception to the universal method.
    • Changed isOneOf to a static method that takes a Material, which can be used for XBlock and other things to improve performance.
  19. Use setColor method it's fixed now.

    That will still throw an exception from valueOf, it needs to be getMaterial
    Note: getMaterial is still more efficient than valueOf, even if you know the exact material name.

    Anyways, yeah. That's basically what's happening but optimized.
    #139 CryptoMorin, Dec 21, 2019
    Last edited: Dec 21, 2019
  20. Code (Java):
                        XBlock.setColor(block, DyeColor.RED);
    Like this?