55
66import javax .annotation .Nonnull ;
77import javax .annotation .Nullable ;
8+ import java .util .HashMap ;
9+ import java .util .Map ;
810
911/**
1012 * Represents a mapping of potion data types to Minecraft's {@link PotionType},
1416 * <p>
1517 * Designed to follow the modern style used in Spigot and Paper APIs as of Minecraft 1.20 and above.
1618 */
17- public enum PotionData {
19+ public enum PotionTypeWrapper {
1820 /**
1921 * Uncraftable potion (special case).
2022 */
@@ -186,24 +188,31 @@ public enum PotionData {
186188 /**
187189 * Slow Falling potion, long duration.
188190 */
189- LONG_SLOW_FALLING (PotionType .SLOW_FALLING , PotionModifier .LONG );;
191+ LONG_SLOW_FALLING (PotionType .SLOW_FALLING , PotionModifier .LONG );
190192
193+ private static final Map <String , PotionTypeWrapper > POTION_TYPE_NAME = new HashMap <>();
191194 private final PotionType potionType ;
192195 private final PotionModifier potionModifier ;
193196 private final float serverVersion = ItemCreator .getServerVersion ();
194197
195198 /**
196199 * Constructs a new {@code PotionData} entry.
197200 *
198- * @param potionType The base {@link PotionType} associated with this potion data,
199- * or {@code null} for special cases like MUNDANE or WATER.
200- * @param potionModifier The {@link PotionModifier} modifier for the potion, e.g., NORMAL, LONG, or STRONG.
201+ * @param potionType The base {@link PotionType} associated with this potion data,
202+ * or {@code null} for special cases like MUNDANE or WATER.
203+ * @param potionModifier The {@link PotionModifier} modifier for the potion, e.g., NORMAL, LONG, or STRONG.
201204 */
202- PotionData (@ Nonnull final PotionType potionType , @ Nonnull final PotionModifier potionModifier ) {
205+ PotionTypeWrapper (@ Nonnull final PotionType potionType , @ Nonnull final PotionModifier potionModifier ) {
203206 this .potionType = potionType ;
204207 this .potionModifier = potionModifier ;
205208 }
206209
210+ static {
211+ for (PotionTypeWrapper data : values ()) {
212+ POTION_TYPE_NAME .put (data .getPotionType ().name (), data );
213+ }
214+ }
215+
207216 /**
208217 * Retrieves the associated {@link PotionType} for this enum constant. Handles version differences
209218 * and special cases like uncraftable or water potions.
@@ -220,35 +229,72 @@ public PotionType getPotionType() {
220229 }
221230
222231 /**
223- * Find the portion mapping from the bukkit potion type.
232+ * Finds the {@link PotionTypeWrapper} corresponding to a Bukkit {@link PotionType}.
233+ * <p>
234+ * This method provides a fast lookup for modern potion mappings and is the recommended
235+ * way to resolve wrappers when working with Bukkit's potion system on 1.20.2 and newer.
236+ * Older Minecraft versions do not offer the same variety of potion types, if you need
237+ * compatibility from 1.8.8 and up, use {@link #findPotionByName(String)} instead.
238+ * </p>
224239 *
225- * @param bukkitPortionType the type you want to find.
226- * @return the PotionData instance or null if it could not find the PotionType .
240+ * @param bukkitPotionType the Bukkit {@link PotionType} to find.
241+ * @return the matching {@link PotionTypeWrapper}, or {@code null} if no mapping exists .
227242 */
228243 @ Nullable
229- public static PotionData findPotionByType (PotionType bukkitPortionType ) {
230- PotionData [] potionTypes = values ();
231- for (PotionData potion : potionTypes ) {
232- if (potion .getPotionType () == bukkitPortionType )
233- return potion ;
234- }
235- return null ;
244+ public static PotionTypeWrapper findPotionByType (final PotionType bukkitPotionType ) {
245+ return POTION_TYPE_NAME .get (bukkitPotionType .name ());
236246 }
237247
238248 /**
239- * Find the portion from the bukkit potion type.
249+ * Finds the {@link PotionTypeWrapper} associated with the given potion name.
250+ * <p>
251+ * This method supports both modern and legacy potion naming. If the provided name matches
252+ * an entry in {@code POTION_TYPE_NAME}, that entry will be returned first.
253+ * Otherwise, it attempts to resolve the name using {@link PotionTypeWrapper#valueOf(String)}.
254+ * </p>
255+ *
256+ * <p><strong>Note:</strong> Using legacy potion names is discouraged, as it prevents
257+ * easy retrieval of potion effect types. Prefer modern {@link PotionType} values
258+ * when possible (see {@link PotionTypeWrapper}), and then use {@link #getModifier()}
259+ * to obtain the correct potion modifier.</p>
240260 *
241- * @param bukkitPortionType the type you want to find.
242- * @return the PotionData instance or null if it could not find the PotionType .
261+ * @param name the potion name to find (case-insensitive) .
262+ * @return the corresponding {@link PotionTypeWrapper}, or {@code null} if no match is found .
243263 */
244264 @ Nullable
245- public static PotionType findPotionByName (String bukkitPortionType ) {
246- PotionType [] potionTypes = PotionType .values ();
247- String bukkitPortion = bukkitPortionType .toUpperCase ();
248- for (PotionType potion : potionTypes ) {
249- if (potion .name ().equals (bukkitPortion ))
250- return potion ;
265+ public static PotionTypeWrapper findPotionByName (final String name ) {
266+ String bukkitPortion = name .toUpperCase ();
267+ PotionTypeWrapper potionTypeWrapper = POTION_TYPE_NAME .get (bukkitPortion );
268+ if (potionTypeWrapper != null )
269+ return potionTypeWrapper ;
270+ try {
271+ return PotionTypeWrapper .valueOf (bukkitPortion );
272+ } catch (IllegalArgumentException e ) {
273+ return null ;
251274 }
275+ }
276+
277+ /**
278+ * Resolves the Bukkit {@link PotionType} from its string name.
279+ * <p>
280+ * This method internally uses {@link #findPotionByName(String)} to obtain the
281+ * corresponding {@link PotionTypeWrapper}, and then returns its underlying
282+ * {@link PotionType}.
283+ * </p>
284+ *
285+ * <p><strong>Note:</strong> On Minecraft versions below 1.20.2, many potions
286+ * do not have distinct {@link PotionType}s. This method may therefore return a
287+ * less specific type or {@code null} if the enum name is not valid.</p>
288+ *
289+ * @param bukkitPotionType the name of the Bukkit potion type (case-insensitive).
290+ * @return the corresponding {@link PotionType}, or {@code null} if not found.
291+ */
292+ @ Nullable
293+ public static PotionType findPotionTypeByName (String bukkitPotionType ) {
294+ String bukkitPotion = bukkitPotionType .toUpperCase ();
295+ PotionTypeWrapper potionByName = findPotionByName (bukkitPotion );
296+ if (potionByName != null )
297+ return potionByName .getPotionType ();
252298 return null ;
253299 }
254300
@@ -324,12 +370,12 @@ private PotionType getPotionMapping() {
324370 * Attempting to get the uncraftable type, this default back
325371 * to mundane on newer Minecraft versions like 1.21 and beyond.
326372 *
327- * @return A {@link PotionType#UNCRAFTABLE} if it exist
373+ * @return A {@link PotionType#UNCRAFTABLE} if it exists
328374 * other cases {@link PotionType#MUNDANE}
329375 */
330376 @ Nonnull
331377 private static PotionType getUncraftable () {
332- PotionType potion = findPotionByName ("UNCRAFTABLE" );
378+ PotionType potion = findPotionTypeByName ("UNCRAFTABLE" );
333379 return potion != null ? potion : PotionType .MUNDANE ;
334380 }
335381
0 commit comments