From 7009dd0d11bfa6bb170e6f91d1c801a8e0ed8199 Mon Sep 17 00:00:00 2001 From: 1wair <1wairesd.com.industries@gmail.com> Date: Sun, 31 May 2026 20:23:08 +0200 Subject: [PATCH] fix: replace PatternType.getByIdentifier() with PatternTypeProvider PatternType.getByIdentifier() causes IncompatibleClassChangeError on 1.19.4 due to a mismatch between Methodref and InterfaceMethodref bytecode constants when compiled against a newer API. Introduce PatternTypeProvider with two implementations: - LegacyPatternTypeProvider: iterates PatternType.values() for 1.19.4 and older where PatternType is still an enum - ModernPatternTypeProvider: uses Registry.BANNER_PATTERN for 1.20.5+ Update MetaItemStack.addBannerMeta to resolve PatternType through the provider instead of calling the deprecated static method directly. --- .../com/earth2me/essentials/Essentials.java | 5 ++ .../earth2me/essentials/MetaItemStack.java | 23 ++------- .../providers/LegacyPatternTypeProvider.java | 49 +++++++++++++++++++ .../ess3/provider/PatternTypeProvider.java | 13 +++++ .../providers/ModernPatternTypeProvider.java | 39 +++++++++++++++ 5 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 providers/1_12Provider/src/main/java/net/ess3/provider/providers/LegacyPatternTypeProvider.java create mode 100644 providers/BaseProviders/src/main/java/net/ess3/provider/PatternTypeProvider.java create mode 100644 providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernPatternTypeProvider.java diff --git a/Essentials/src/main/java/com/earth2me/essentials/Essentials.java b/Essentials/src/main/java/com/earth2me/essentials/Essentials.java index 8f8e378900f..5170a694a63 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/main/java/com/earth2me/essentials/Essentials.java @@ -79,6 +79,8 @@ import net.ess3.provider.providers.FlatSpawnEggProvider; import net.ess3.provider.providers.LegacyBannerDataProvider; import net.ess3.provider.providers.LegacyBiomeNameProvider; +import net.ess3.provider.providers.LegacyPatternTypeProvider; +import net.ess3.provider.providers.ModernPatternTypeProvider; import net.ess3.provider.providers.LegacyDamageEventProvider; import net.ess3.provider.providers.LegacyInventoryViewProvider; import net.ess3.provider.providers.LegacyItemUnbreakableProvider; @@ -342,6 +344,9 @@ public void onEnable() { //Banner Meta Provider providerFactory.registerProvider(LegacyBannerDataProvider.class, BaseBannerDataProvider.class); + // Pattern Type Provider + providerFactory.registerProvider(LegacyPatternTypeProvider.class, ModernPatternTypeProvider.class); + // Server State Provider providerFactory.registerProvider(ReflServerStateProvider.class, PaperServerStateProvider.class); diff --git a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java index 48c6984a32f..fc2ca038e4d 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java +++ b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java @@ -13,6 +13,7 @@ import net.ess3.api.TranslatableException; import net.ess3.provider.BannerDataProvider; import net.ess3.provider.ItemUnbreakableProvider; +import net.ess3.provider.PatternTypeProvider; import net.ess3.provider.PotionMetaProvider; import org.bukkit.Color; import org.bukkit.DyeColor; @@ -712,22 +713,15 @@ public void addBannerMeta(final CommandSource sender, final boolean allowShortNa throw new TranslatableException("invalidBanner", split[1]); } - PatternType patternType = null; - try { - //noinspection removal - patternType = PatternType.getByIdentifier(split[0]); - } catch (final Exception ignored) { - } + final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]); final BannerMeta meta = (BannerMeta) stack.getItemMeta(); if (split[0].equalsIgnoreCase("basecolor")) { final Color color = Color.fromRGB(Integer.parseInt(split[1])); ess.provider(BannerDataProvider.class).setBaseColor(stack, DyeColor.getByColor(color)); } else if (patternType != null) { - //noinspection removal - final PatternType type = PatternType.getByIdentifier(split[0]); final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1]))); - final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type); + final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, patternType); meta.addPattern(pattern); } @@ -739,12 +733,7 @@ public void addBannerMeta(final CommandSource sender, final boolean allowShortNa throw new TranslatableException("invalidBanner", split[1]); } - PatternType patternType = null; - try { - //noinspection removal - patternType = PatternType.getByIdentifier(split[0]); - } catch (final Exception ignored) { - } + final PatternType patternType = ess.provider(PatternTypeProvider.class).getPatternTypeByIdentifier(split[0]); // Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795 final BlockStateMeta meta = (BlockStateMeta) stack.getItemMeta(); @@ -753,10 +742,8 @@ public void addBannerMeta(final CommandSource sender, final boolean allowShortNa final Color color = Color.fromRGB(Integer.parseInt(split[1])); banner.setBaseColor(DyeColor.getByColor(color)); } else if (patternType != null) { - //noinspection removal - final PatternType type = PatternType.getByIdentifier(split[0]); final DyeColor color = DyeColor.getByColor(Color.fromRGB(Integer.parseInt(split[1]))); - final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, type); + final org.bukkit.block.banner.Pattern pattern = new org.bukkit.block.banner.Pattern(color, patternType); banner.addPattern(pattern); } banner.update(); diff --git a/providers/1_12Provider/src/main/java/net/ess3/provider/providers/LegacyPatternTypeProvider.java b/providers/1_12Provider/src/main/java/net/ess3/provider/providers/LegacyPatternTypeProvider.java new file mode 100644 index 00000000000..b3b8a6bb19f --- /dev/null +++ b/providers/1_12Provider/src/main/java/net/ess3/provider/providers/LegacyPatternTypeProvider.java @@ -0,0 +1,49 @@ +package net.ess3.provider.providers; + +import net.ess3.provider.PatternTypeProvider; +import net.essentialsx.providers.ProviderData; +import net.essentialsx.providers.ProviderTest; +import org.bukkit.block.banner.PatternType; + +/** + * Legacy PatternType provider for Minecraft 1.19.4 and older. + * + * In these versions PatternType is an enum and getByIdentifier() is a static + * method on the enum itself. Calling it via the modern API path causes an + * IncompatibleClassChangeError because the compiled bytecode expects a + * Methodref constant but finds an InterfaceMethodref (or vice-versa). + * + * This provider avoids that by iterating over PatternType.values() and + * comparing identifiers manually, which works on all versions where + * PatternType is still an enum. + */ +@ProviderData(description = "Legacy (enum-based) PatternType Provider", weight = 0) +public class LegacyPatternTypeProvider implements PatternTypeProvider { + + @Override + public PatternType getPatternTypeByIdentifier(final String identifier) { + if (identifier == null) { + return null; + } + for (final PatternType type : PatternType.values()) { + //noinspection removal + if (type.getIdentifier().equalsIgnoreCase(identifier)) { + return type; + } + } + return null; + } + + @ProviderTest + public static boolean test() { + try { + // PatternType is an enum in 1.19.4 and older. + // In 1.20.5+ it became a Keyed interface backed by Registry, + // so values() no longer exists and this will throw. + PatternType.class.getMethod("values"); + return true; + } catch (final Throwable ignored) { + return false; + } + } +} diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/PatternTypeProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/PatternTypeProvider.java new file mode 100644 index 00000000000..3673227f08d --- /dev/null +++ b/providers/BaseProviders/src/main/java/net/ess3/provider/PatternTypeProvider.java @@ -0,0 +1,13 @@ +package net.ess3.provider; + +import org.bukkit.block.banner.PatternType; + +public interface PatternTypeProvider extends Provider { + /** + * Returns the PatternType matching the given identifier string, or null if not found. + * + * @param identifier the pattern identifier (e.g. "stripe_top") + * @return the matching PatternType, or null + */ + PatternType getPatternTypeByIdentifier(String identifier); +} diff --git a/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernPatternTypeProvider.java b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernPatternTypeProvider.java new file mode 100644 index 00000000000..befc3c95000 --- /dev/null +++ b/providers/BaseProviders/src/main/java/net/ess3/provider/providers/ModernPatternTypeProvider.java @@ -0,0 +1,39 @@ +package net.ess3.provider.providers; + +import net.ess3.provider.PatternTypeProvider; +import net.essentialsx.providers.ProviderData; +import net.essentialsx.providers.ProviderTest; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.block.banner.PatternType; + +/** + * Modern PatternType provider for Minecraft 1.20.5+. + * + * In 1.20.5 PatternType was changed from an enum to a Keyed interface backed + * by Registry.BANNER_PATTERN. This provider uses the Registry API to look up + * pattern types by their identifier. + */ +@ProviderData(description = "Modern (Registry-based) PatternType Provider", weight = 1) +public class ModernPatternTypeProvider implements PatternTypeProvider { + + @Override + public PatternType getPatternTypeByIdentifier(final String identifier) { + if (identifier == null) { + return null; + } + return Registry.BANNER_PATTERN.get(NamespacedKey.minecraft(identifier.toLowerCase())); + } + + @ProviderTest + public static boolean test() { + try { + // Registry.BANNER_PATTERN was added in 1.20.5 when PatternType + // was converted from an enum to a Registry-backed Keyed type. + Registry.class.getField("BANNER_PATTERN"); + return true; + } catch (final Throwable ignored) { + return false; + } + } +}