From 99eeb79087a67a93ecccd15260862951daeead5e Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 23 Apr 2021 13:57:13 -0700
Subject: [PATCH] More World API (#3850)

---
 Spigot-API-Patches/More-World-API.patch    | 131 ++++++++++++++++++
 Spigot-Server-Patches/More-World-API.patch | 146 +++++++++++++++++++++
 2 files changed, 277 insertions(+)
 create mode 100644 Spigot-API-Patches/More-World-API.patch
 create mode 100644 Spigot-Server-Patches/More-World-API.patch

diff --git a/Spigot-API-Patches/More-World-API.patch b/Spigot-API-Patches/More-World-API.patch
new file mode 100644
index 0000000000..25cb73a096
--- /dev/null
+++ b/Spigot-API-Patches/More-World-API.patch
@@ -0,0 +1,131 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <jake.m.potrebic@gmail.com>
+Date: Tue, 7 Jul 2020 10:53:22 -0700
+Subject: [PATCH] More World API
+
+
+diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/World.java
++++ b/src/main/java/org/bukkit/World.java
+@@ -0,0 +0,0 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad
+     @Nullable
+     public Location locateNearestStructure(@NotNull Location origin, @NotNull StructureType structureType, int radius, boolean findUnexplored);
+ 
++    // Paper start
++    /**
++     * Locates the nearest biome based on an origin, biome type, and radius to search.
++     * Step defaults to {@code 8}.
++     *
++     * @param origin Origin location
++     * @param biome Biome to find
++     * @param radius radius to search
++     * @return Location of biome or null if not found in specified radius
++     */
++    @Nullable
++    Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius);
++
++    /**
++     * Locates the nearest biome based on an origin, biome type, and radius to search
++     * and step
++     *
++     * @param origin Origin location
++     * @param biome Biome to find
++     * @param radius radius to search
++     * @param step Search step 1 would mean checking every block, 8 would be every 8th block
++     * @return Location of biome or null if not found in specified radius
++     */
++    @Nullable
++    Location locateNearestBiome(@NotNull Location origin, @NotNull Biome biome, int radius, int step);
++
++    /**
++     * Checks if the world:
++     * <ul>
++     *     <li>evaporates water</li>
++     *     <li>dries sponges</li>
++     *     <li>has lava spread faster and further</li>
++     * </ul>
++     *
++     * @return true if ultrawarm, false if not
++     */
++    boolean isUltrawarm();
++
++    /**
++     * Checks if the world is natural.
++     * <p>
++     *     If {@code false}, compasses will spin randomly in the world.
++     *     If {@code true}, nether portals will spawn zombified piglins.
++     * </p>
++     *
++     * @return true or false
++     */
++    boolean isNatural();
++
++    /**
++     * Gets the coordinate scaling of this world.
++     *
++     * @return the coordinate scale
++     */
++    double getCoordinateScale();
++
++    /**
++     * Checks if the world has skylight access
++     *
++     * @return whether there is skylight
++     */
++    boolean hasSkylight();
++
++    /**
++     * Checks if the world has a bedrock ceiling
++     *
++     * @return whether the world has a bedrock ceiling
++     */
++    boolean hasBedrockCeiling();
++
++    /**
++     * Checks if piglins will turn into Zombified Piglins in this world
++     *
++     * @return whether Piglins will <i>not</i> transform
++     */
++    boolean isPiglinSafe();
++
++    /**
++     * Checks if beds work
++     *
++     * @return whether beds work
++     */
++    boolean doesBedWork();
++
++    /**
++     * Checks if respawn anchors work
++     *
++     * @return whether respawn anchors work
++     */
++    boolean doesRespawnAnchorWork();
++
++    /**
++     * Checks if this world supports raids
++     *
++     * @return whether this world supports raids
++     */
++    boolean hasRaids();
++
++    /**
++     * Checks if this world has a fixed time
++     *
++     * @return whether this world has fixed time
++     */
++    boolean isFixedTime();
++
++    /**
++     * Gets the collection of materials that burn infinitely in this world.
++     *
++     * @return the materials that will forever stay lit by fire
++     */
++    @NotNull
++    Collection<Material> getInfiniburn();
++    // Paper end
++
+     // Spigot start
+     /**
+      * Returns the view distance used for this world.
diff --git a/Spigot-Server-Patches/More-World-API.patch b/Spigot-Server-Patches/More-World-API.patch
new file mode 100644
index 0000000000..b9d3bbd8bb
--- /dev/null
+++ b/Spigot-Server-Patches/More-World-API.patch
@@ -0,0 +1,146 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <jake.m.potrebic@gmail.com>
+Date: Tue, 7 Jul 2020 10:52:34 -0700
+Subject: [PATCH] More World API
+
+
+diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/level/WorldServer.java
++++ b/src/main/java/net/minecraft/server/level/WorldServer.java
+@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
+         return !this.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit
+     }
+ 
++    public BlockPosition getNearestBiome(BiomeBase biomeBase, BlockPosition blockPosition, int radius, int step) { return this.a(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER
+     @Nullable
+     public BlockPosition a(BiomeBase biomebase, BlockPosition blockposition, int i, int j) {
+         return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().a(blockposition.getX(), blockposition.getY(), blockposition.getZ(), i, j, (biomebase1) -> {
+@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
+         return this.savingDisabled;
+     }
+ 
++    public IRegistryCustom getWorldCustomRegistry() { return r(); } // Paper - OBFHELPER
+     @Override
+     public IRegistryCustom r() {
+         return this.server.getCustomRegistry();
+diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java
++++ b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java
+@@ -0,0 +0,0 @@ public class DimensionManager {
+     public static IRegistryCustom.Dimension a(IRegistryCustom.Dimension iregistrycustom_dimension) {
+         IRegistryWritable<DimensionManager> iregistrywritable = iregistrycustom_dimension.b(IRegistry.K);
+ 
+-        iregistrywritable.a(DimensionManager.OVERWORLD, (Object) DimensionManager.OVERWORLD_IMPL, Lifecycle.stable());
+-        iregistrywritable.a(DimensionManager.l, (Object) DimensionManager.m, Lifecycle.stable());
+-        iregistrywritable.a(DimensionManager.THE_NETHER, (Object) DimensionManager.THE_NETHER_IMPL, Lifecycle.stable());
+-        iregistrywritable.a(DimensionManager.THE_END, (Object) DimensionManager.THE_END_IMPL, Lifecycle.stable());
++        iregistrywritable.a(DimensionManager.OVERWORLD, DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); // Paper - decompile fix
++        iregistrywritable.a(DimensionManager.l, DimensionManager.m, Lifecycle.stable()); // Paper - decompile fix
++        iregistrywritable.a(DimensionManager.THE_NETHER, DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); // Paper - decompile fix
++        iregistrywritable.a(DimensionManager.THE_END, DimensionManager.THE_END_IMPL, Lifecycle.stable()); // Paper - decompile fix
+         return iregistrycustom_dimension;
+     }
+ 
+@@ -0,0 +0,0 @@ public class DimensionManager {
+     public static RegistryMaterials<WorldDimension> a(IRegistry<DimensionManager> iregistry, IRegistry<BiomeBase> iregistry1, IRegistry<GeneratorSettingBase> iregistry2, long i) {
+         RegistryMaterials<WorldDimension> registrymaterials = new RegistryMaterials<>(IRegistry.M, Lifecycle.experimental());
+ 
+-        registrymaterials.a(WorldDimension.THE_NETHER, (Object) (new WorldDimension(() -> {
++        registrymaterials.a(WorldDimension.THE_NETHER, (new WorldDimension(() -> { // Paper - decompile fix
+             return (DimensionManager) iregistry.d(DimensionManager.THE_NETHER);
+         }, b(iregistry1, iregistry2, i))), Lifecycle.stable());
+-        registrymaterials.a(WorldDimension.THE_END, (Object) (new WorldDimension(() -> {
++        registrymaterials.a(WorldDimension.THE_END, (new WorldDimension(() -> { // Paper - decompile fix
+             return (DimensionManager) iregistry.d(DimensionManager.THE_END);
+         }, a(iregistry1, iregistry2, i))), Lifecycle.stable());
+         return registrymaterials;
+@@ -0,0 +0,0 @@ public class DimensionManager {
+         return this.E[i];
+     }
+ 
++    public Tag<Block> getInfiniburnTag() { return o(); } // Paper - OBFHELPER
+     public Tag<Block> o() {
+         Tag<Block> tag = TagsBlock.a().a(this.infiniburn);
+ 
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+@@ -0,0 +0,0 @@ public class CraftWorld implements World {
+         return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
+     }
+ 
++    // Paper start
++    @Override
++    public Location locateNearestBiome(Location origin, Biome biome, int radius) {
++        return this.locateNearestBiome(origin, biome, radius, 8);
++    }
++
++    @Override
++    public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) {
++        BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ());
++        BlockPosition nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().b(IRegistry.ay), biome), originPos, radius, step);
++        return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
++    }
++
++    @Override
++    public boolean isUltrawarm() {
++        return getHandle().getDimensionManager().isNether();
++    }
++
++    @Override
++    public boolean isNatural() {
++        return getHandle().getDimensionManager().isNatural();
++    }
++
++    @Override
++    public double getCoordinateScale() {
++        return getHandle().getDimensionManager().getCoordinateScale();
++    }
++
++    @Override
++    public boolean hasSkylight() {
++        return getHandle().getDimensionManager().hasSkyLight();
++    }
++
++    @Override
++    public boolean hasBedrockCeiling() {
++        return getHandle().getDimensionManager().hasSkyLight();
++    }
++
++    @Override
++    public boolean isPiglinSafe() {
++        return getHandle().getDimensionManager().isPiglinSafe();
++    }
++
++    @Override
++    public boolean doesBedWork() {
++        return getHandle().getDimensionManager().isBedWorks();
++    }
++
++    @Override
++    public boolean doesRespawnAnchorWork() {
++        return getHandle().getDimensionManager().isRespawnAnchorWorks();
++    }
++
++    @Override
++    public boolean hasRaids() {
++        return getHandle().getDimensionManager().hasRaids();
++    }
++
++    @Override
++    public boolean isFixedTime() {
++        return getHandle().getDimensionManager().isFixedTime();
++    }
++
++    @Override
++    public Collection<org.bukkit.Material> getInfiniburn() {
++        return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().getDimensionManager().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial));
++    }
++    // Paper end
++
+     @Override
+     public Raid locateNearestRaid(Location location, int radius) {
+         Validate.notNull(location, "Location cannot be null");