From 6e485c34094802fcc629dd0a5ecd1c5bd3c1936d Mon Sep 17 00:00:00 2001
From: Axionize <154778082+Axionize@users.noreply.github.com>
Date: Sun, 29 Sep 2024 18:06:13 -0400
Subject: [PATCH] Configurable per-world void damage offset/damage(#11436)

---
 .../api/Void-damage-configuration-API.patch   | 65 +++++++++++++
 .../Add-and-fix-missing-BlockFadeEvents.patch |  2 +-
 patches/server/Paper-config-files.patch       |  3 +
 .../Void-damage-configuration-API.patch       | 94 +++++++++++++++++++
 4 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 patches/api/Void-damage-configuration-API.patch
 create mode 100644 patches/server/Void-damage-configuration-API.patch

diff --git a/patches/api/Void-damage-configuration-API.patch b/patches/api/Void-damage-configuration-API.patch
new file mode 100644
index 0000000000..1100eb6c9a
--- /dev/null
+++ b/patches/api/Void-damage-configuration-API.patch
@@ -0,0 +1,65 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Axionize <154778082+Axionize@users.noreply.github.com>
+Date: Wed, 25 Sep 2024 04:43:26 -0400
+Subject: [PATCH] Void damage configuration 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 @@ import org.jetbrains.annotations.Nullable;
+  */
+ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed, net.kyori.adventure.audience.ForwardingAudience { // Paper
+ 
++    // Paper start - void damage configuration
++    /**
++     * Checks if void damage is enabled on this world.
++     *
++     * @return true if enabled
++     */
++    boolean isVoidDamageEnabled();
++
++    /**
++     * Sets whether void damage is enabled on this world.
++     *
++     * @param enabled true to enable void damage
++     */
++    void setVoidDamageEnabled(boolean enabled);
++
++    /**
++     * Gets the damage applied to the player when they are in the void in this world.
++     * Check {@link #isVoidDamageEnabled()} to see if void damage is enabled.
++     *
++     * @return amount of damage to apply
++     * @see #isVoidDamageEnabled()
++     */
++    float getVoidDamageAmount();
++
++    /**
++     * Sets the damage applied to the player when they are in the void in this world.
++     * Check {@link #isVoidDamageEnabled()} to see if void damage is enabled.
++     *
++     * @param voidDamageAmount amount of damage to apply
++     */
++    void setVoidDamageAmount(float voidDamageAmount);
++
++    /**
++     * Gets the offset applied to {@link #getMinHeight()} to determine the height at which void damage starts to apply.
++     *
++     * @return offset from min build height
++     * @see #isVoidDamageEnabled()
++     */
++    double getVoidDamageMinBuildHeightOffset();
++
++    /**
++     * Sets the offset applied to {@link #getMinHeight()} to determine the height at which void damage starts to apply.
++     *
++     * @param minBuildHeightOffset offset from min build height
++     */
++    void setVoidDamageMinBuildHeightOffset(double minBuildHeightOffset);
++    // Paper end - void damage configuration
++
+     // Paper start
+     /**
+      * @return The amount of Entities in this world
diff --git a/patches/server/Add-and-fix-missing-BlockFadeEvents.patch b/patches/server/Add-and-fix-missing-BlockFadeEvents.patch
index 74a03a6345..1fae68e304 100644
--- a/patches/server/Add-and-fix-missing-BlockFadeEvents.patch
+++ b/patches/server/Add-and-fix-missing-BlockFadeEvents.patch
@@ -7,7 +7,7 @@ Beyond calling the BlockFadeEvent in more places, this patch also aims
 to pass the proper replacement state to the event, specifically for
 potentially waterlogged block states fading.
 
-Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com
+Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
 
 diff --git a/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch
index c82a6ef2df..67392ccae7 100644
--- a/patches/server/Paper-config-files.patch
+++ b/patches/server/Paper-config-files.patch
@@ -1455,6 +1455,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import java.util.IdentityHashMap;
 +import java.util.List;
 +import java.util.Map;
++import java.util.OptionalDouble;
 +import java.util.function.Function;
 +import java.util.stream.Collectors;
 +import net.minecraft.Util;
@@ -1838,6 +1839,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        public boolean disableExplosionKnockback = false;
 +        public boolean generateFlatBedrock = false;
 +        public FrostedIce frostedIce;
++        public DoubleOr.Disabled voidDamageAmount = new DoubleOr.Disabled(OptionalDouble.of(4));
++        public double voidDamageMinBuildHeightOffset = -64.0;
 +
 +        public class FrostedIce extends ConfigurationPart {
 +            public boolean enabled = true;
diff --git a/patches/server/Void-damage-configuration-API.patch b/patches/server/Void-damage-configuration-API.patch
new file mode 100644
index 0000000000..96614aa47d
--- /dev/null
+++ b/patches/server/Void-damage-configuration-API.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Axionize <154778082+Axionize@users.noreply.github.com>
+Date: Sun, 29 Sep 2024 14:20:42 -0700
+Subject: [PATCH] Void damage configuration API
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+     }
+ 
+     public void checkBelowWorld() {
++        if (!this.level.getWorld().isVoidDamageEnabled()) return; // Paper - check if void damage is enabled on the world
++
+         // Paper start - Configurable nether ceiling damage
+-        if (this.getY() < (double) (this.level.getMinBuildHeight() - 64) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER
++        if (this.getY() < (double) (this.level.getMinBuildHeight() + this.level.getWorld().getVoidDamageMinBuildHeightOffset())  || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER // Paper - use configured min build height offset
+             && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
+             && (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
+             // Paper end - Configurable nether ceiling damage
+diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
+@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ 
+     @Override
+     protected void onBelowWorld() {
+-        this.hurt(this.damageSources().fellOutOfWorld(), 4.0F);
++        this.hurt(this.damageSources().fellOutOfWorld(), this.level().getWorld().getVoidDamageAmount()); // Paper - use configured void damage amount
+     }
+ 
+     protected void updateSwingTime() {
+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 extends CraftRegionAccessor implements World {
+     private final Object2IntOpenHashMap<SpawnCategory> spawnCategoryLimit = new Object2IntOpenHashMap<>();
+     private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
+     private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
++    // Paper start - void damage configuration
++    private boolean voidDamageEnabled;
++    private float voidDamageAmount;
++    private double voidDamageMinBuildHeightOffset;
++
++    @Override
++    public boolean isVoidDamageEnabled() {
++        return this.voidDamageEnabled;
++    }
++
++    @Override
++    public void setVoidDamageEnabled(final boolean enabled) {
++        this.voidDamageEnabled = enabled;
++    }
++
++    @Override
++    public float getVoidDamageAmount() {
++        return this.voidDamageAmount;
++    }
++
++    @Override
++    public void setVoidDamageAmount(float voidDamageAmount) {
++        this.voidDamageAmount = voidDamageAmount;
++    }
++
++    @Override
++    public double getVoidDamageMinBuildHeightOffset() {
++        return this.voidDamageMinBuildHeightOffset;
++    }
++
++    @Override
++    public void setVoidDamageMinBuildHeightOffset(double minBuildHeightOffset) {
++        this.voidDamageMinBuildHeightOffset = minBuildHeightOffset;
++    }
++    // Paper end - void damage configuration
+ 
+     // Paper start - Provide fast information methods
+     @Override
+@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+             }
+         }
+         // Paper end - per world spawn limits
++
++        // Paper start - per world void damage height
++        this.voidDamageEnabled = this.world.paperConfig().environment.voidDamageAmount.enabled();
++        this.voidDamageMinBuildHeightOffset = this.world.paperConfig().environment.voidDamageMinBuildHeightOffset;
++        this.voidDamageAmount = (float) this.world.paperConfig().environment.voidDamageAmount.or(0);
++        // Paper end - per world void damage height
+     }
+ 
+     @Override