From 2c33bdaee381b2601f90d4ec3f00e131334a2d74 Mon Sep 17 00:00:00 2001 From: xGinko Date: Fri, 20 Dec 2024 15:54:37 +0100 Subject: [PATCH] patch new exploit and update plugin --- AnarchyExploitFixesFolia/build.gradle.kts | 1 - .../me/xginko/aef/AnarchyExploitFixes.java | 16 ++--- .../java/me/xginko/aef/modules/AEFModule.java | 3 + .../aef/modules/packets/BigMessages.java | 58 +++++++++++++++++++ AnarchyExploitFixesLegacy/build.gradle.kts | 1 - .../me/xginko/aef/AnarchyExploitFixes.java | 16 ++--- .../java/me/xginko/aef/config/Config.java | 12 ++-- .../java/me/xginko/aef/modules/AEFModule.java | 3 + .../aef/modules/packets/BigMessages.java | 58 +++++++++++++++++++ .../kotlin/me.xginko.aef.wrapper.gradle.kts | 6 +- gradle/libs.versions.toml | 6 +- .../me/xginko/aef/utils/MaterialUtil.java | 36 ++++++------ 12 files changed, 158 insertions(+), 58 deletions(-) create mode 100755 AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/BigMessages.java create mode 100755 AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/packets/BigMessages.java diff --git a/AnarchyExploitFixesFolia/build.gradle.kts b/AnarchyExploitFixesFolia/build.gradle.kts index 389677fa..1af7ff82 100755 --- a/AnarchyExploitFixesFolia/build.gradle.kts +++ b/AnarchyExploitFixesFolia/build.gradle.kts @@ -27,7 +27,6 @@ tasks.shadowJar { archiveFileName = "${rootProject.name}-${project.name}-${project.version}.${archiveExtension.get()}" exclude( "com/cryptomorin/xseries/XBiome*", - "com/cryptomorin/xseries/XPotion*", "com/cryptomorin/xseries/NMSExtras*", "com/cryptomorin/xseries/NoteBlockMusic*", "com/cryptomorin/xseries/SkullCacheListener*" diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/AnarchyExploitFixes.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/AnarchyExploitFixes.java index 858dc5cb..0c00f75c 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/AnarchyExploitFixes.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/AnarchyExploitFixes.java @@ -1,7 +1,6 @@ package me.xginko.aef; -import com.github.retrooper.packetevents.PacketEvents; -import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; +import de.tr7zw.changeme.nbtapi.NBT; import me.xginko.aef.commands.AEFCommand; import me.xginko.aef.config.Config; import me.xginko.aef.config.LanguageCache; @@ -49,13 +48,6 @@ public final class AnarchyExploitFixes extends JavaPlugin { @Override public void onLoad() { PlatformUtil.load(); - isPacketEventsInstalled = getServer().getPluginManager().getPlugin("packetevents") != null; - if (isPacketEventsInstalled) { - // Configure and load packetevents - PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); - PacketEvents.getAPI().getSettings().kickOnPacketException(true).reEncodeByDefault(false); - PacketEvents.getAPI().load(); - } } @Override @@ -76,6 +68,7 @@ public void onEnable() { prefixedLogger = ComponentLogger.logger(getLogger().getName()); unPrefixedLogger = ComponentLogger.logger(""); + isPacketEventsInstalled = getServer().getPluginManager().getPlugin("packetevents") != null; if (!isPacketEventsInstalled) { Stream.of(" ", " _ _ _ _ _ ", @@ -128,8 +121,8 @@ public void onEnable() { prefixedLogger.info("Registering Permissions"); AEFPermission.registerPermissions(); - prefixedLogger.info("Initializing PacketEvents"); - PacketEvents.getAPI().init(); + prefixedLogger.info("Initializing NBT-API"); + NBT.preloadApi(); prefixedLogger.info("Ready."); } @@ -138,7 +131,6 @@ public void onEnable() { public void onDisable() { if (isPacketEventsInstalled) { AEFModule.disableAll(); - PacketEvents.getAPI().terminate(); } if (languageCacheMap != null) { languageCacheMap.clear(); diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/AEFModule.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/AEFModule.java index f07e7192..2fe006b1 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/AEFModule.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/AEFModule.java @@ -6,6 +6,7 @@ import me.xginko.aef.modules.packets.PacketModule; import me.xginko.aef.utils.models.ConditionalEnableable; import me.xginko.aef.utils.models.Disableable; +import me.xginko.aef.utils.models.Enableable; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; import org.reflections.Reflections; @@ -75,6 +76,8 @@ public static void reloadModules() { AnarchyExploitFixes.prefixedLogger().warn("Failed initialising module class '{}'.", moduleClass.getSimpleName(), t); } } + + ENABLED_MODULES.forEach(Enableable::enable); } protected void error(String message, Throwable throwable) { diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/BigMessages.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/BigMessages.java new file mode 100755 index 00000000..2bcd6fb0 --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/BigMessages.java @@ -0,0 +1,58 @@ +package me.xginko.aef.modules.packets; + +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.nio.charset.StandardCharsets; + +public class BigMessages extends PacketModule { + + private final int charLimit; + private final boolean log, kick; + + public BigMessages() { + super("patches.message-char-limit", PacketListenerPriority.HIGHEST); + config.addComment(configPath + ".enable", """ + Sets a character limit for command and message packets to prevent a lag exploit."""); + this.charLimit = config.getInt(configPath + ".max-characters", 512); + this.log = config.getBoolean(configPath + ".log", false); + this.kick = config.getBoolean(configPath + ".kick-player", false); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", true); + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (event.isCancelled()) return; + + if ( + event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE + || event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND + || event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND_UNSIGNED + ) { + if (isStringTooBig(new PacketWrapper<>(event))) { + event.setCancelled(true); + onCancel(log, kick, event.getUser()); + } + } + } + + private boolean isStringTooBig(PacketWrapper packetWrapper) { + int strBufLen = packetWrapper.readVarInt(); + + // Check if the received encoded string buffer length is zero or longer than maximum allowed + if (strBufLen < 0 || strBufLen > charLimit * 4) { + return true; + } + + // The received string length is longer than maximum allowed + return ByteBufHelper.toString(packetWrapper.buffer, ByteBufHelper.readerIndex(packetWrapper.buffer), strBufLen, StandardCharsets.UTF_8) + .length() > charLimit; + } +} diff --git a/AnarchyExploitFixesLegacy/build.gradle.kts b/AnarchyExploitFixesLegacy/build.gradle.kts index 66dd01ba..327191e4 100755 --- a/AnarchyExploitFixesLegacy/build.gradle.kts +++ b/AnarchyExploitFixesLegacy/build.gradle.kts @@ -21,7 +21,6 @@ tasks { archiveFileName = "${rootProject.name}-${project.name}-${project.version}.${archiveExtension.get()}" exclude( "com/cryptomorin/xseries/XBiome*", - "com/cryptomorin/xseries/XPotion*", "com/cryptomorin/xseries/NMSExtras*", "com/cryptomorin/xseries/NoteBlockMusic*", "com/cryptomorin/xseries/SkullCacheListener*" diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/AnarchyExploitFixes.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/AnarchyExploitFixes.java index 388ca23d..bcc2722b 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/AnarchyExploitFixes.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/AnarchyExploitFixes.java @@ -1,7 +1,6 @@ package me.xginko.aef; -import com.github.retrooper.packetevents.PacketEvents; -import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; +import de.tr7zw.changeme.nbtapi.NBT; import me.xginko.aef.commands.AEFCommand; import me.xginko.aef.config.Config; import me.xginko.aef.config.Datastore; @@ -50,13 +49,6 @@ public final class AnarchyExploitFixes extends JavaPlugin { @Override public void onLoad() { PlatformUtil.load(); - isPacketEventsInstalled = getServer().getPluginManager().getPlugin("packetevents") != null; - if (isPacketEventsInstalled) { - // Configure and load packetevents - PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); - PacketEvents.getAPI().getSettings().kickOnPacketException(true).reEncodeByDefault(false); - PacketEvents.getAPI().load(); - } } @Override @@ -70,6 +62,7 @@ public void onEnable() { prefixedLogger = LoggerFactory.getLogger(getLogger().getName()); unPrefixedLogger = LoggerFactory.getLogger(""); + isPacketEventsInstalled = getServer().getPluginManager().getPlugin("packetevents") != null; if (!isPacketEventsInstalled) { Stream.of(" ", " _ _ _ _ _ ", @@ -128,8 +121,8 @@ public void onEnable() { prefixedLogger.info("Registering Permissions"); AEFPermission.registerPermissions(); - prefixedLogger.info("Initializing PacketEvents"); - PacketEvents.getAPI().init(); + prefixedLogger.info("Initializing NBT-API"); + NBT.preloadApi(); prefixedLogger.info("Ready."); } @@ -138,7 +131,6 @@ public void onEnable() { public void onDisable() { if (isPacketEventsInstalled) { AEFModule.disableAll(); - PacketEvents.getAPI().terminate(); } if (languageCacheMap != null) { languageCacheMap.clear(); diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/config/Config.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/config/Config.java index cee5e9ce..d3d5c002 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/config/Config.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/config/Config.java @@ -115,14 +115,10 @@ public Config() throws Exception { "Plays XP pickup sound to alert players when theyre going\n" + "above the limit."); String configuredSound = getString("elytra.elytra-speed.sound", XSound.ENTITY_EXPERIENCE_ORB_PICKUP.name()); - Sound parsedSound; - try { - parsedSound = XSound.valueOf(configuredSound).parseSound(); - } catch (IllegalArgumentException e) { - AnarchyExploitFixes.prefixedLogger().warn(" Sound '"+configuredSound+"' does not exist in XSound. Using default."); - parsedSound = XSound.ENTITY_EXPERIENCE_ORB_PICKUP.parseSound(); - } - this.elytra_too_fast_sound = parsedSound; + this.elytra_too_fast_sound = XSound.of(configuredSound).orElseGet(() -> { + AnarchyExploitFixes.prefixedLogger().warn(" Sound '{}' does not exist in XSound. Using default.", configuredSound); + return XSound.ENTITY_EXPERIENCE_ORB_PICKUP; + }).get(); this.elytra_teleport_back = getBoolean("elytra.elytra-speed.teleport-instead-of-canceling-movement", false, "Recommended to leave false if you dont experience any issues."); this.elytra_enable_global = getBoolean("elytra.elytra-speed.Global-Settings.enable", true); diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/AEFModule.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/AEFModule.java index f07e7192..2fe006b1 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/AEFModule.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/AEFModule.java @@ -6,6 +6,7 @@ import me.xginko.aef.modules.packets.PacketModule; import me.xginko.aef.utils.models.ConditionalEnableable; import me.xginko.aef.utils.models.Disableable; +import me.xginko.aef.utils.models.Enableable; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; import org.reflections.Reflections; @@ -75,6 +76,8 @@ public static void reloadModules() { AnarchyExploitFixes.prefixedLogger().warn("Failed initialising module class '{}'.", moduleClass.getSimpleName(), t); } } + + ENABLED_MODULES.forEach(Enableable::enable); } protected void error(String message, Throwable throwable) { diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/packets/BigMessages.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/packets/BigMessages.java new file mode 100755 index 00000000..a662634f --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/packets/BigMessages.java @@ -0,0 +1,58 @@ +package me.xginko.aef.modules.packets; + +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.PacketWrapper; + +import java.nio.charset.StandardCharsets; + +public class BigMessages extends PacketModule { + + private final int charLimit; + private final boolean log, kick; + + public BigMessages() { + super("patches.message-char-limit", PacketListenerPriority.HIGHEST); + config.addComment(configPath + ".enable", + "Sets a character limit for command and message packets to prevent a lag exploit."); + this.charLimit = config.getInt(configPath + ".max-characters", 512); + this.log = config.getBoolean(configPath + ".log", false); + this.kick = config.getBoolean(configPath + ".kick-player", false); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", true); + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + if (event.isCancelled()) return; + + if ( + event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE + || event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND + || event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND_UNSIGNED + ) { + if (isStringTooBig(new PacketWrapper<>(event))) { + event.setCancelled(true); + onCancel(log, kick, event.getUser()); + } + } + } + + private boolean isStringTooBig(PacketWrapper packetWrapper) { + int strBufLen = packetWrapper.readVarInt(); + + // Check if the received encoded string buffer length is zero or longer than maximum allowed + if (strBufLen < 0 || strBufLen > charLimit * 4) { + return true; + } + + // The received string length is longer than maximum allowed + return ByteBufHelper.toString(packetWrapper.buffer, ByteBufHelper.readerIndex(packetWrapper.buffer), strBufLen, StandardCharsets.UTF_8) + .length() > charLimit; + } +} diff --git a/build-logic/src/main/kotlin/me.xginko.aef.wrapper.gradle.kts b/build-logic/src/main/kotlin/me.xginko.aef.wrapper.gradle.kts index 93e49421..01b8b2ee 100755 --- a/build-logic/src/main/kotlin/me.xginko.aef.wrapper.gradle.kts +++ b/build-logic/src/main/kotlin/me.xginko.aef.wrapper.gradle.kts @@ -43,10 +43,10 @@ repositories { } dependencies { - compileOnly("com.github.retrooper:packetevents-spigot:2.6.0") // PacketEvents to patch packet based exploits - api("com.github.cryptomorin:XSeries:11.3.0") // Crossversion entitytype and material support + compileOnly("com.github.retrooper:packetevents-spigot:2.7.0") // PacketEvents to patch packet based exploits + api("com.github.cryptomorin:XSeries:12.1.0") // Crossversion entitytype and material support api("com.github.thatsmusic99:ConfigurationMaster-API:v2.0.0-rc.1") // ConfigurationMaster for enhanced config management - api("de.tr7zw:item-nbt-api:2.14.0") // NBT API for cross version nbt tag handling + api("de.tr7zw:item-nbt-api:2.14.1") // NBT API for cross version nbt tag handling api("org.bstats:bstats-bukkit:3.0.2") // Bukkit bStats api("org.apache.commons:commons-math3:3.6.1") // FastMath api("org.reflections:reflections:0.10.2") // Reflections diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1634a011..dd017e6c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,8 +13,8 @@ hikaricp = "com.zaxxer:HikariCP:5.1.0" [plugins] runpaper = { id = "xyz.jpenilla.run-paper", version = "2.3.1" } -shadow = { id = "io.github.goooler.shadow", version = "8.1.8" } -userdev = { id = "io.papermc.paperweight.userdev", version = "1.7.4" } -downgradeJava = { id = "xyz.wagyourtail.jvmdowngrader", version = "1.2.0" } +shadow = { id = "com.gradleup.shadow", version = "8.3.5" } +userdev = { id = "io.papermc.paperweight.userdev", version = "1.7.7" } +downgradeJava = { id = "xyz.wagyourtail.jvmdowngrader", version = "1.2.1" } [bundles] diff --git a/shared/src/main/java/me/xginko/aef/utils/MaterialUtil.java b/shared/src/main/java/me/xginko/aef/utils/MaterialUtil.java index 89ac27eb..99bec95d 100755 --- a/shared/src/main/java/me/xginko/aef/utils/MaterialUtil.java +++ b/shared/src/main/java/me/xginko/aef/utils/MaterialUtil.java @@ -32,76 +32,76 @@ public class MaterialUtil { public static final Set LECTERN_BOOKS = XTag.ITEMS_LECTERN_BOOKS.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set SIGNS = XTag.SIGNS.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set TRAPDOORS = XTag.TRAPDOORS.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set PRESSURE_PLATES = XTag.PRESSURE_PLATES.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set SHULKER_BOXES = XTag.SHULKER_BOXES.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set ANVILS = XTag.ANVIL.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set BEDS = XTag.BEDS.getValues().stream() .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set POTIONS = Arrays.stream(XMaterial.values()) .filter(xMaterial -> xMaterial.name().toUpperCase().contains("POTION")) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set PISTONS = Arrays.stream(XMaterial.values()) .filter(xMaterial -> xMaterial.name().toUpperCase().contains("PISTON")) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set SPAWN_EGGS = Arrays.stream(XMaterial.values()) .filter(xMaterial -> xMaterial.name().toUpperCase().endsWith("_SPAWN_EGG")) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set SLAB_LIKE = Stream.concat( Arrays.stream(XMaterial.values()).filter(xMaterial -> xMaterial.name().toUpperCase().endsWith("_SLAB")), Stream.of(XMaterial.SCULK_SENSOR, XMaterial.CALIBRATED_SCULK_SENSOR, XMaterial.SCULK_SHRIEKER)) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set PLAYER_HEADS = Stream.of( XMaterial.PLAYER_HEAD, XMaterial.PLAYER_WALL_HEAD) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set REDSTONE = Stream.of( XMaterial.REDSTONE, XMaterial.REDSTONE_WIRE) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); // Blocks that the player gets lowered into slightly when walking on them @@ -110,7 +110,7 @@ public class MaterialUtil { XMaterial.FARMLAND, XMaterial.MUD) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set SOLID_INDESTRUCTIBLES = Stream.of( @@ -122,11 +122,11 @@ public class MaterialUtil { XMaterial.BARRIER, XMaterial.COMMAND_BLOCK) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static final Set INDESTRUCTIBLES = Stream.concat(SOLID_INDESTRUCTIBLES.stream(), - Stream.of(XMaterial.END_PORTAL.parseMaterial())) + Stream.of(XMaterial.END_PORTAL.get())) .filter(Objects::nonNull) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); @@ -141,11 +141,11 @@ public class MaterialUtil { XMaterial.TADPOLE_BUCKET, XMaterial.POWDER_SNOW_BUCKET) .filter(XMaterial::isSupported) - .map(XMaterial::parseMaterial) + .map(XMaterial::get) .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); public static boolean isElytra(@Nullable ItemStack itemStack) { - return itemStack != null && itemStack.getType() == XMaterial.ELYTRA.parseMaterial(); + return itemStack != null && itemStack.getType() == XMaterial.ELYTRA.get(); } @SuppressWarnings("deprecation")