From a45964ac0eaa4d42832a7792b8f8d6b189e92756 Mon Sep 17 00:00:00 2001
From: Bukkit/Spigot <noreply+git-bukkit@papermc.io>
Date: Fri, 1 Nov 2024 08:05:31 +1100
Subject: [PATCH] #1073: Make Biome an interface

By: DerFrZocker <derrieple@gmail.com>
---
 .../src/main/java/org/bukkit/Registry.java    |   2 +-
 .../main/java/org/bukkit/UnsafeValues.java    |   4 +
 .../src/main/java/org/bukkit/block/Biome.java | 191 +++++++++++-------
 3 files changed, 119 insertions(+), 78 deletions(-)

diff --git a/paper-api/src/main/java/org/bukkit/Registry.java b/paper-api/src/main/java/org/bukkit/Registry.java
index fbc1a540a2..774f9bd0ef 100644
--- a/paper-api/src/main/java/org/bukkit/Registry.java
+++ b/paper-api/src/main/java/org/bukkit/Registry.java
@@ -105,7 +105,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
      *
      * @see Biome
      */
-    Registry<Biome> BIOME = new SimpleRegistry<>(Biome.class);
+    Registry<Biome> BIOME = Objects.requireNonNull(Bukkit.getRegistry(Biome.class), "No registry present for Biome. This is a bug.");
     /**
      * Server block types.
      *
diff --git a/paper-api/src/main/java/org/bukkit/UnsafeValues.java b/paper-api/src/main/java/org/bukkit/UnsafeValues.java
index dd049e9a4f..752fef0205 100644
--- a/paper-api/src/main/java/org/bukkit/UnsafeValues.java
+++ b/paper-api/src/main/java/org/bukkit/UnsafeValues.java
@@ -4,6 +4,7 @@ import com.google.common.collect.Multimap;
 import org.bukkit.advancement.Advancement;
 import org.bukkit.attribute.Attribute;
 import org.bukkit.attribute.AttributeModifier;
+import org.bukkit.block.Biome;
 import org.bukkit.block.data.BlockData;
 import org.bukkit.damage.DamageEffect;
 import org.bukkit.damage.DamageSource;
@@ -133,4 +134,7 @@ public interface UnsafeValues {
 
     @ApiStatus.Internal
     <B extends Keyed> B get(Registry<B> registry, NamespacedKey key);
+
+    @ApiStatus.Internal
+    Biome getCustomBiome();
 }
diff --git a/paper-api/src/main/java/org/bukkit/block/Biome.java b/paper-api/src/main/java/org/bukkit/block/Biome.java
index 2201b63e73..f46932a12f 100644
--- a/paper-api/src/main/java/org/bukkit/block/Biome.java
+++ b/paper-api/src/main/java/org/bukkit/block/Biome.java
@@ -1,97 +1,134 @@
 package org.bukkit.block;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 import java.util.Locale;
+import org.bukkit.Bukkit;
+import org.bukkit.FeatureFlag;
 import org.bukkit.Keyed;
 import org.bukkit.MinecraftExperimental;
 import org.bukkit.NamespacedKey;
+import org.bukkit.Registry;
+import org.bukkit.packs.DataPack;
+import org.bukkit.util.OldEnum;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 
 /**
- * Holds all accepted Biomes in the default server
+ * Holds all accepted Biomes in the server.
+ * <p>
+ * The Biomes listed in this interface are present in the default server
+ * or can be enabled via a {@link FeatureFlag}.
+ * There may be additional biomes present in the server, for example from a {@link DataPack}
+ * which can be accessed via {@link Registry#BIOME}.
  */
-public enum Biome implements Keyed {
-    OCEAN,
-    PLAINS,
-    DESERT,
-    WINDSWEPT_HILLS,
-    FOREST,
-    TAIGA,
-    SWAMP,
-    MANGROVE_SWAMP,
-    RIVER,
-    NETHER_WASTES,
-    THE_END,
-    FROZEN_OCEAN,
-    FROZEN_RIVER,
-    SNOWY_PLAINS,
-    MUSHROOM_FIELDS,
-    BEACH,
-    JUNGLE,
-    SPARSE_JUNGLE,
-    DEEP_OCEAN,
-    STONY_SHORE,
-    SNOWY_BEACH,
-    BIRCH_FOREST,
-    DARK_FOREST,
-    SNOWY_TAIGA,
-    OLD_GROWTH_PINE_TAIGA,
-    WINDSWEPT_FOREST,
-    SAVANNA,
-    SAVANNA_PLATEAU,
-    BADLANDS,
-    WOODED_BADLANDS,
-    SMALL_END_ISLANDS,
-    END_MIDLANDS,
-    END_HIGHLANDS,
-    END_BARRENS,
-    WARM_OCEAN,
-    LUKEWARM_OCEAN,
-    COLD_OCEAN,
-    DEEP_LUKEWARM_OCEAN,
-    DEEP_COLD_OCEAN,
-    DEEP_FROZEN_OCEAN,
-    THE_VOID,
-    SUNFLOWER_PLAINS,
-    WINDSWEPT_GRAVELLY_HILLS,
-    FLOWER_FOREST,
-    ICE_SPIKES,
-    OLD_GROWTH_BIRCH_FOREST,
-    OLD_GROWTH_SPRUCE_TAIGA,
-    WINDSWEPT_SAVANNA,
-    ERODED_BADLANDS,
-    BAMBOO_JUNGLE,
-    SOUL_SAND_VALLEY,
-    CRIMSON_FOREST,
-    WARPED_FOREST,
-    BASALT_DELTAS,
-    DRIPSTONE_CAVES,
-    LUSH_CAVES,
-    DEEP_DARK,
-    MEADOW,
-    GROVE,
-    SNOWY_SLOPES,
-    FROZEN_PEAKS,
-    JAGGED_PEAKS,
-    STONY_PEAKS,
-    CHERRY_GROVE,
+public interface Biome extends OldEnum<Biome>, Keyed {
+
+    Biome OCEAN = getBiome("ocean");
+    Biome PLAINS = getBiome("plains");
+    Biome DESERT = getBiome("desert");
+    Biome WINDSWEPT_HILLS = getBiome("windswept_hills");
+    Biome FOREST = getBiome("forest");
+    Biome TAIGA = getBiome("taiga");
+    Biome SWAMP = getBiome("swamp");
+    Biome MANGROVE_SWAMP = getBiome("mangrove_swamp");
+    Biome RIVER = getBiome("river");
+    Biome NETHER_WASTES = getBiome("nether_wastes");
+    Biome THE_END = getBiome("the_end");
+    Biome FROZEN_OCEAN = getBiome("frozen_ocean");
+    Biome FROZEN_RIVER = getBiome("frozen_river");
+    Biome SNOWY_PLAINS = getBiome("snowy_plains");
+    Biome MUSHROOM_FIELDS = getBiome("mushroom_fields");
+    Biome BEACH = getBiome("beach");
+    Biome JUNGLE = getBiome("jungle");
+    Biome SPARSE_JUNGLE = getBiome("sparse_jungle");
+    Biome DEEP_OCEAN = getBiome("deep_ocean");
+    Biome STONY_SHORE = getBiome("stony_shore");
+    Biome SNOWY_BEACH = getBiome("snowy_beach");
+    Biome BIRCH_FOREST = getBiome("birch_forest");
+    Biome DARK_FOREST = getBiome("dark_forest");
+    Biome SNOWY_TAIGA = getBiome("snowy_taiga");
+    Biome OLD_GROWTH_PINE_TAIGA = getBiome("old_growth_pine_taiga");
+    Biome WINDSWEPT_FOREST = getBiome("windswept_forest");
+    Biome SAVANNA = getBiome("savanna");
+    Biome SAVANNA_PLATEAU = getBiome("savanna_plateau");
+    Biome BADLANDS = getBiome("badlands");
+    Biome WOODED_BADLANDS = getBiome("wooded_badlands");
+    Biome SMALL_END_ISLANDS = getBiome("small_end_islands");
+    Biome END_MIDLANDS = getBiome("end_midlands");
+    Biome END_HIGHLANDS = getBiome("end_highlands");
+    Biome END_BARRENS = getBiome("end_barrens");
+    Biome WARM_OCEAN = getBiome("warm_ocean");
+    Biome LUKEWARM_OCEAN = getBiome("lukewarm_ocean");
+    Biome COLD_OCEAN = getBiome("cold_ocean");
+    Biome DEEP_LUKEWARM_OCEAN = getBiome("deep_lukewarm_ocean");
+    Biome DEEP_COLD_OCEAN = getBiome("deep_cold_ocean");
+    Biome DEEP_FROZEN_OCEAN = getBiome("deep_frozen_ocean");
+    Biome THE_VOID = getBiome("the_void");
+    Biome SUNFLOWER_PLAINS = getBiome("sunflower_plains");
+    Biome WINDSWEPT_GRAVELLY_HILLS = getBiome("windswept_gravelly_hills");
+    Biome FLOWER_FOREST = getBiome("flower_forest");
+    Biome ICE_SPIKES = getBiome("ice_spikes");
+    Biome OLD_GROWTH_BIRCH_FOREST = getBiome("old_growth_birch_forest");
+    Biome OLD_GROWTH_SPRUCE_TAIGA = getBiome("old_growth_spruce_taiga");
+    Biome WINDSWEPT_SAVANNA = getBiome("windswept_savanna");
+    Biome ERODED_BADLANDS = getBiome("eroded_badlands");
+    Biome BAMBOO_JUNGLE = getBiome("bamboo_jungle");
+    Biome SOUL_SAND_VALLEY = getBiome("soul_sand_valley");
+    Biome CRIMSON_FOREST = getBiome("crimson_forest");
+    Biome WARPED_FOREST = getBiome("warped_forest");
+    Biome BASALT_DELTAS = getBiome("basalt_deltas");
+    Biome DRIPSTONE_CAVES = getBiome("dripstone_caves");
+    Biome LUSH_CAVES = getBiome("lush_caves");
+    Biome DEEP_DARK = getBiome("deep_dark");
+    Biome MEADOW = getBiome("meadow");
+    Biome GROVE = getBiome("grove");
+    Biome SNOWY_SLOPES = getBiome("snowy_slopes");
+    Biome FROZEN_PEAKS = getBiome("frozen_peaks");
+    Biome JAGGED_PEAKS = getBiome("jagged_peaks");
+    Biome STONY_PEAKS = getBiome("stony_peaks");
+    Biome CHERRY_GROVE = getBiome("cherry_grove");
     @ApiStatus.Experimental
     @MinecraftExperimental(MinecraftExperimental.Requires.WINTER_DROP)
-    PALE_GARDEN,
+    Biome PALE_GARDEN = Registry.BIOME.get(NamespacedKey.minecraft("pale_garden"));
+
     /**
      * Represents a custom Biome
+     *
+     * @deprecated Biome is no longer an enum, custom biomes will have their own biome instance.
      */
-    CUSTOM;
-
-    private final NamespacedKey key;
-
-    private Biome() {
-        this.key = NamespacedKey.minecraft(name().toLowerCase(Locale.ROOT));
-    }
+    @Deprecated(since = "1.21.3")
+    Biome CUSTOM = Bukkit.getUnsafe().getCustomBiome();
 
     @NotNull
-    @Override
-    public NamespacedKey getKey() {
-        return key;
+    private static Biome getBiome(@NotNull String key) {
+        return Registry.BIOME.getOrThrow(NamespacedKey.minecraft(key));
+    }
+
+    /**
+     * @param name of the biome.
+     * @return the biome with the given name.
+     * @deprecated only for backwards compatibility, use {@link Registry#get(NamespacedKey)} instead.
+     */
+    @NotNull
+    @Deprecated(since = "1.21.3")
+    static Biome valueOf(@NotNull String name) {
+        if ("CUSTOM".equals(name)) {
+            return Biome.CUSTOM;
+        }
+
+        Biome biome = Bukkit.getUnsafe().get(Registry.BIOME, NamespacedKey.fromString(name.toLowerCase(Locale.ROOT)));
+        Preconditions.checkArgument(biome != null, "No biome found with the name %s", name);
+        return biome;
+    }
+
+    /**
+     * @return an array of all known biomes.
+     * @deprecated use {@link Registry#iterator()}.
+     */
+    @NotNull
+    @Deprecated(since = "1.21.3")
+    static Biome[] values() {
+        return Lists.newArrayList(Registry.BIOME).toArray(new Biome[0]);
     }
 }