From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 31 May 2016 22:53:50 -0400
Subject: [PATCH] Fix global sound handling

* Only send global sounds to same world if limiting radius
* respect global sound events gamerule

Co-authored-by: Evan McCarthy <evanmccarthy@outlook.com>
Co-authored-by: lexikiq <noellekiq@gmail.com>
Co-authored-by: Aikar <aikar@aikar.co>

diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 57c13407fd20bcdd17642b0e6078f10082aea87b..0a7dec5ff89c94503908ad011fe7da8dd8256685 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1324,7 +1324,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
 
     @Override
     public void levelEvent(@Nullable Player player, int eventId, BlockPos pos, int data) {
-        this.server.getPlayerList().broadcast(player, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 64.0D, this.dimension(), new ClientboundLevelEventPacket(eventId, pos, data, false));
+        this.server.getPlayerList().broadcast(player, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 64.0D, this.dimension(), new ClientboundLevelEventPacket(eventId, pos, data, false)); // Paper - diff on change (the 64.0 distance is used as defaults for sound ranges in spigot config for ender dragon, end portal and wither)
     }
 
     public int getLogicalHeight() {
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
index 53ff70fff0d12a151d13481a3226f72af57cce3e..993ccde9e6ee769ce51cdfa4ff06cfe1bd27bbb0 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -679,11 +679,12 @@ public class EnderDragon extends Mob implements Enemy {
                 // CraftBukkit start - Use relative location for far away sounds
                 // this.level().globalLevelEvent(1028, this.blockPosition(), 0);
                 int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16;
-                for (net.minecraft.server.level.ServerPlayer player : this.level().getServer().getPlayerList().players) {
+                for (net.minecraft.server.level.ServerPlayer player : this.level().getPlayersForGlobalSoundGamerule()) { // Paper - respect global sound events gamerule
                     double deltaX = this.getX() - player.getX();
                     double deltaZ = this.getZ() - player.getZ();
                     double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
-                    if ( this.level().spigotConfig.dragonDeathSoundRadius > 0 && distanceSquared > this.level().spigotConfig.dragonDeathSoundRadius * this.level().spigotConfig.dragonDeathSoundRadius ) continue; // Spigot
+                    final double soundRadiusSquared = this.level().getGlobalSoundRangeSquared(config -> config.dragonDeathSoundRadius); // Paper - respect global sound events gamerule
+                    if ( !this.level().getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS) && distanceSquared > soundRadiusSquared ) continue; // Spigot // Paper - respect global sound events gamerule
                     if (distanceSquared > viewDistance * viewDistance) {
                         double deltaLength = Math.sqrt(distanceSquared);
                         double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance;
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
index ff04f392163c2f7b1015ce379706d19a5f655f5c..b0ac85dc3c67d2e4d70dfb09d4e8fc349aba14d2 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -278,11 +278,12 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
                     // CraftBukkit start - Use relative location for far away sounds
                     // this.level().globalLevelEvent(1023, new BlockPosition(this), 0);
                     int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16;
-                    for (ServerPlayer player : (List<ServerPlayer>) MinecraftServer.getServer().getPlayerList().players) {
+                    for (ServerPlayer player : this.level().getPlayersForGlobalSoundGamerule()) { // Paper - respect global sound events gamerule
                         double deltaX = this.getX() - player.getX();
                         double deltaZ = this.getZ() - player.getZ();
                         double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
-                        if ( this.level().spigotConfig.witherSpawnSoundRadius > 0 && distanceSquared > this.level().spigotConfig.witherSpawnSoundRadius * this.level().spigotConfig.witherSpawnSoundRadius ) continue; // Spigot
+                        final double soundRadiusSquared = this.level().getGlobalSoundRangeSquared(config -> config.witherSpawnSoundRadius); // Paper - respect global sound events gamerule
+                        if ( !this.level().getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS) && distanceSquared > soundRadiusSquared ) continue; // Spigot // Paper - respect global sound events gamerule
                         if (distanceSquared > viewDistance * viewDistance) {
                             double deltaLength = Math.sqrt(distanceSquared);
                             double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance;
diff --git a/src/main/java/net/minecraft/world/item/EnderEyeItem.java b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
index 6df874ac5091896be5edddd362c11958c0ad815b..37cfb9694dc06f693b7b54f20bc31dfd9f95c76c 100644
--- a/src/main/java/net/minecraft/world/item/EnderEyeItem.java
+++ b/src/main/java/net/minecraft/world/item/EnderEyeItem.java
@@ -65,11 +65,12 @@ public class EnderEyeItem extends Item {
                     // world.b(1038, blockposition1.c(1, 0, 1), 0);
                     int viewDistance = world.getCraftServer().getViewDistance() * 16;
                     BlockPos soundPos = blockposition1.offset(1, 0, 1);
-                    for (ServerPlayer player : world.getServer().getPlayerList().players) {
+                    for (ServerPlayer player : world.getPlayersForGlobalSoundGamerule()) { // Paper - respect global sound events gamerule
                         double deltaX = soundPos.getX() - player.getX();
                         double deltaZ = soundPos.getZ() - player.getZ();
                         double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
-                        if (world.spigotConfig.endPortalSoundRadius > 0 && distanceSquared > world.spigotConfig.endPortalSoundRadius * world.spigotConfig.endPortalSoundRadius) continue; // Spigot
+                        final double soundRadiusSquared = world.getGlobalSoundRangeSquared(config -> config.endPortalSoundRadius); // Paper - respect global sound events gamerule
+                        if (!world.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_GLOBAL_SOUND_EVENTS) && distanceSquared > soundRadiusSquared) continue; // Spigot // Paper - respect global sound events gamerule
                         if (distanceSquared > viewDistance * viewDistance) {
                             double deltaLength = Math.sqrt(distanceSquared);
                             double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 95fc5fc293eb7d77868fa0a37beb792ee0620fcd..edcab2dd4070703101ed9bef86f320093be6c1cb 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1262,4 +1262,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
 
         private ExplosionInteraction() {}
     }
+    // Paper start - respect global sound events gamerule
+    public List<net.minecraft.server.level.ServerPlayer> getPlayersForGlobalSoundGamerule() {
+        return this.getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS) ? ((ServerLevel) this).getServer().getPlayerList().players : ((ServerLevel) this).players();
+    }
+
+    public double getGlobalSoundRangeSquared(java.util.function.Function<org.spigotmc.SpigotWorldConfig, Integer> rangeFunction) {
+        final double range = rangeFunction.apply(this.spigotConfig);
+        return range <= 0 ? 64.0 * 64.0 : range * range; // 64 is taken from default in ServerLevel#levelEvent
+    }
+    // Paper end - respect global sound events gamerule
 }
