package net.glowstone.util;

import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import net.glowstone.GlowWorld;
import net.glowstone.entity.GlowPlayer;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;

public class SoundUtil {

    public static void playSoundAtLocationExcept(Location location, Sound sound, float volume, float pitch, GlowPlayer... exclude) {
        if (location == null || sound == null) {
            return;
        }
        GlowWorld world = (GlowWorld) location.getWorld();
        double radiusSquared = volume * volume * 256;
        world.getRawPlayers().stream().filter(player ->
            player.getLocation().distanceSquared(location) <= radiusSquared
                && !Arrays.asList(exclude).contains(player))
            .forEach(player -> player.playSound(location, sound, volume, pitch));
    }

    public static void playSoundPitchRange(Location location, Sound sound, float volume, float pitchBase, float pitchRange, boolean allowNegative, GlowPlayer... exclude) {
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        float pitch = pitchBase;
        if (allowNegative) {
            pitch += randomReal(pitchRange);
        } else {
            pitch += rand.nextFloat() * pitchRange;
        }
        playSoundAtLocationExcept(location, sound, volume, pitch, exclude);
    }

    public static void playSoundPitchRange(Location location, Sound sound, float volume, float pitchBase, float pitchRange, GlowPlayer... exclude) {
        playSoundPitchRange(location, sound, volume, pitchBase, pitchRange, true, exclude);
    }

    public static float randomReal(float range) {
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        return (rand.nextFloat() - rand.nextFloat()) * range;
    }

    /**
     * Convert a string to a SoundCategory. The comparison is done on the name and is not case-sensitive.
     *
     * @param category The string name of the category
     * @return The matching SoundCategory, null if none.
     */
    public static SoundCategory buildSoundCategory(final String category) {
        if (category == null) {
            return null;
        }

        for (final SoundCategory soundCategory : SoundCategory.values()) {
            if (category.equalsIgnoreCase(soundCategory.name())) {
                return soundCategory;
            }
        }

        return null;
    }
}

@@ -279,16 +279,343 @@
 Util %7B%0A%0A
+    /**%0A     * Plays a sound with a random pitch, but excludes one player from hearing it.%0A     *%0A     * @param location the sound location%0A     * @param sound the sound to play%0A     * @param volume the volume multiplier%0A     * @param pitch the pitch modifier%0A     * @param exclude the player not to play the sound for%0A     */%0A
     publ
@@ -692,32 +692,44 @@
 d, float volume,
+%0A           
  float pitch, Gl
@@ -1007,24 +1007,28 @@
             
+    
 player.getLo
@@ -1095,16 +1095,24 @@
         
+        
 && !Arra
@@ -1160,16 +1160,20 @@
         
+  
+  
 .forEach
@@ -1233,32 +1233,604 @@
 pitch));%0A    %7D%0A%0A
+    /**%0A     * Plays a sound with a random pitch, but excludes one player from hearing it.%0A     *%0A     * @param location the sound location%0A     * @param sound the sound to play%0A     * @param volume the volume multiplier%0A     * @param pitchBase if %7B@code allowNegative%7D, the average pitch modifier; otherwise, the minimum%0A     * @param pitchRange the maximum deviation of the pitch modifier compared to %7B@code pitchBase%7D%0A     * @param allowNegative if true, distribution is triangular rather than uniform%0A     * @param exclude the player not to play the sound for%0A     */%0A
     public stati
@@ -1893,32 +1893,44 @@
 d, float volume,
+%0A           
  float pitchBase
@@ -2416,16 +2416,28 @@
  volume,
+%0A           
  float p
@@ -2866,16 +2866,23 @@
 d is not
+%0A     *
  case-se
@@ -3152,33 +3152,32 @@
 null;%0A        %7D%0A
-%0A
         for (fin
@@ -3360,25 +3360,24 @@
 %7D%0A        %7D%0A
-%0A
         retu

Fix CheckStyle issues in util/SoundUtil.java (#735)