#938: Various Sound API improvements

By: Jishuna <joshl5324@gmail.com>
This commit is contained in:
Bukkit/Spigot 2023-11-17 19:54:43 +13:00
parent 44cbcb80d4
commit 1f322369a0
4 changed files with 203 additions and 35 deletions

View file

@ -9,110 +9,123 @@ public enum Instrument {
/** /**
* Piano is the standard instrument for a note block. * Piano is the standard instrument for a note block.
*/ */
PIANO(0x0), PIANO(0x0, Sound.BLOCK_NOTE_BLOCK_HARP),
/** /**
* Bass drum is normally played when a note block is on top of a * Bass drum is normally played when a note block is on top of a
* stone-like block. * stone-like block.
*/ */
BASS_DRUM(0x1), BASS_DRUM(0x1, Sound.BLOCK_NOTE_BLOCK_BASEDRUM),
/** /**
* Snare drum is normally played when a note block is on top of a sandy * Snare drum is normally played when a note block is on top of a sandy
* block. * block.
*/ */
SNARE_DRUM(0x2), SNARE_DRUM(0x2, Sound.BLOCK_NOTE_BLOCK_SNARE),
/** /**
* Sticks are normally played when a note block is on top of a glass * Sticks are normally played when a note block is on top of a glass
* block. * block.
*/ */
STICKS(0x3), STICKS(0x3, Sound.BLOCK_NOTE_BLOCK_HAT),
/** /**
* Bass guitar is normally played when a note block is on top of a wooden * Bass guitar is normally played when a note block is on top of a wooden
* block. * block.
*/ */
BASS_GUITAR(0x4), BASS_GUITAR(0x4, Sound.BLOCK_NOTE_BLOCK_BASS),
/** /**
* Flute is normally played when a note block is on top of a clay block. * Flute is normally played when a note block is on top of a clay block.
*/ */
FLUTE(0x5), FLUTE(0x5, Sound.BLOCK_NOTE_BLOCK_FLUTE),
/** /**
* Bell is normally played when a note block is on top of a gold block. * Bell is normally played when a note block is on top of a gold block.
*/ */
BELL(0x6), BELL(0x6, Sound.BLOCK_NOTE_BLOCK_BELL),
/** /**
* Guitar is normally played when a note block is on top of a woolen block. * Guitar is normally played when a note block is on top of a woolen block.
*/ */
GUITAR(0x7), GUITAR(0x7, Sound.BLOCK_NOTE_BLOCK_GUITAR),
/** /**
* Chime is normally played when a note block is on top of a packed ice * Chime is normally played when a note block is on top of a packed ice
* block. * block.
*/ */
CHIME(0x8), CHIME(0x8, Sound.BLOCK_NOTE_BLOCK_CHIME),
/** /**
* Xylophone is normally played when a note block is on top of a bone block. * Xylophone is normally played when a note block is on top of a bone block.
*/ */
XYLOPHONE(0x9), XYLOPHONE(0x9, Sound.BLOCK_NOTE_BLOCK_XYLOPHONE),
/** /**
* Iron Xylophone is normally played when a note block is on top of a iron block. * Iron Xylophone is normally played when a note block is on top of a iron block.
*/ */
IRON_XYLOPHONE(0xA), IRON_XYLOPHONE(0xA, Sound.BLOCK_NOTE_BLOCK_IRON_XYLOPHONE),
/** /**
* Cow Bell is normally played when a note block is on top of a soul sand block. * Cow Bell is normally played when a note block is on top of a soul sand block.
*/ */
COW_BELL(0xB), COW_BELL(0xB, Sound.BLOCK_NOTE_BLOCK_COW_BELL),
/** /**
* Didgeridoo is normally played when a note block is on top of a pumpkin block. * Didgeridoo is normally played when a note block is on top of a pumpkin block.
*/ */
DIDGERIDOO(0xC), DIDGERIDOO(0xC, Sound.BLOCK_NOTE_BLOCK_DIDGERIDOO),
/** /**
* Bit is normally played when a note block is on top of a emerald block. * Bit is normally played when a note block is on top of a emerald block.
*/ */
BIT(0xD), BIT(0xD, Sound.BLOCK_NOTE_BLOCK_BIT),
/** /**
* Banjo is normally played when a note block is on top of a hay block. * Banjo is normally played when a note block is on top of a hay block.
*/ */
BANJO(0xE), BANJO(0xE, Sound.BLOCK_NOTE_BLOCK_BANJO),
/** /**
* Pling is normally played when a note block is on top of a glowstone block. * Pling is normally played when a note block is on top of a glowstone block.
*/ */
PLING(0xF), PLING(0xF, Sound.BLOCK_NOTE_BLOCK_PLING),
/** /**
* Zombie is normally played when a Zombie Head is on top of the note block. * Zombie is normally played when a Zombie Head is on top of the note block.
*/ */
ZOMBIE, ZOMBIE(Sound.BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE),
/** /**
* Skeleton is normally played when a Skeleton Head is on top of the note block. * Skeleton is normally played when a Skeleton Head is on top of the note block.
*/ */
SKELETON, SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_SKELETON),
/** /**
* Creeper is normally played when a Creeper Head is on top of the note block. * Creeper is normally played when a Creeper Head is on top of the note block.
*/ */
CREEPER, CREEPER(Sound.BLOCK_NOTE_BLOCK_IMITATE_CREEPER),
/** /**
* Dragon is normally played when a Dragon Head is on top of the note block. * Dragon is normally played when a Dragon Head is on top of the note block.
*/ */
DRAGON, DRAGON(Sound.BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON),
/** /**
* Wither Skeleton is normally played when a Wither Skeleton Head is on top of the note block. * Wither Skeleton is normally played when a Wither Skeleton Head is on top of the note block.
*/ */
WITHER_SKELETON, WITHER_SKELETON(Sound.BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON),
/** /**
* Piglin is normally played when a Piglin Head is on top of the note block. * Piglin is normally played when a Piglin Head is on top of the note block.
*/ */
PIGLIN, PIGLIN(Sound.BLOCK_NOTE_BLOCK_IMITATE_PIGLIN),
/** /**
* Custom Sound is normally played when a Player Head with the required data is on top of the note block. * Custom Sound is normally played when a Player Head with the required data is on top of the note block.
*/ */
CUSTOM_HEAD; CUSTOM_HEAD(null);
private final byte type; private final byte type;
private final Sound sound;
private static final Map<Byte, Instrument> BY_DATA = Maps.newHashMap(); private static final Map<Byte, Instrument> BY_DATA = Maps.newHashMap();
private Instrument() { private Instrument(final Sound sound) {
this(-1); this(-1, sound);
} }
private Instrument(final int type) { private Instrument(final int type, final Sound sound) {
this.type = (byte) type; this.type = (byte) type;
this.sound = sound;
}
/**
* Gets the sound associated with this instrument. <br>
* Will be null for {@link Instrument#CUSTOM_HEAD}
*
* @return the sound or null
*/
@Nullable
public Sound getSound() {
return this.sound;
} }
/** /**

View file

@ -118,6 +118,14 @@ public class Note {
} }
} }
private static final float[] pitchArray = new float[25];
static {
for (int i = 0; i <= 24; i++) {
// See https://minecraft.wiki/w/Note_Block#Notes
pitchArray[i] = (float) Math.pow(2, (i - 12) / 12f);
}
}
private final byte note; private final byte note;
/** /**
@ -254,6 +262,16 @@ public class Note {
return Tone.getById(note).isSharped(note); return Tone.getById(note).isSharped(note);
} }
/**
* Gets the pitch of this note. This is the value used with
* {@link World#playSound} or the /playsound command.
*
* @return the pitch
*/
public float getPitch() {
return pitchArray[this.note];
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View file

@ -2109,6 +2109,18 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*/ */
void setSpawnLimit(@NotNull SpawnCategory spawnCategory, int limit); void setSpawnLimit(@NotNull SpawnCategory spawnCategory, int limit);
/**
* Play a note at the provided Location in the World. <br>
* This <i>will</i> work with cake.
* <p>
* This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}.
*
* @param loc The location to play the note
* @param instrument The instrument
* @param note The note
*/
void playNote(@NotNull Location loc, @NotNull Instrument instrument, @NotNull Note note);
/** /**
* Play a Sound at the provided Location in the World. * Play a Sound at the provided Location in the World.
* <p> * <p>
@ -2163,6 +2175,38 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*/ */
void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch); void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch);
/**
* Play a Sound at the provided Location in the World. For sounds with multiple
* variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Location or Sound are null.
*
* @param location The location to play the sound
* @param sound The sound to play
* @param category the category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
void playSound(@NotNull Location location, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/**
* Play a Sound at the provided Location in the World. For sounds with multiple
* variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Location or Sound are null. No sound will
* be heard by the players if their clients do not have the respective sound for
* the value passed.
*
* @param location The location to play the sound
* @param sound The internal sound name to play
* @param category the category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/** /**
* Play a Sound at the location of the provided entity in the World. * Play a Sound at the location of the provided entity in the World.
* <p> * <p>
@ -2213,6 +2257,38 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*/ */
void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch); void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch);
/**
* Play a Sound at the location of the provided entity in the World. For sounds
* with multiple variations passing the same seed will always play the same
* variation.
* <p>
* This function will fail silently if Entity or Sound are null.
*
* @param entity The entity to play the sound
* @param sound The sound to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
void playSound(@NotNull Entity entity, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/**
* Play a Sound at the location of the provided entity in the World. For sounds
* with multiple variations passing the same seed will always play the same
* variation.
* <p>
* This function will fail silently if Entity or Sound are null.
*
* @param entity The entity to play the sound
* @param sound The sound to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/** /**
* Get an array containing the names of all the {@link GameRule}s. * Get an array containing the names of all the {@link GameRule}s.
* *

View file

@ -391,11 +391,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
public void setBedSpawnLocation(@Nullable Location location, boolean force); public void setBedSpawnLocation(@Nullable Location location, boolean force);
/** /**
* Play a note for a player at a location. This requires a note block * Play a note for the player at a location. <br>
* at the particular location (as far as the client is concerned). This * This <i>will</i> work with cake.
* will not work without a note block. This will not work with cake.
* *
* @param loc The location of a note block. * @param loc The location to play the note
* @param instrument The instrument ID. * @param instrument The instrument ID.
* @param note The note ID. * @param note The note ID.
* @deprecated Magic value * @deprecated Magic value
@ -404,11 +403,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
public void playNote(@NotNull Location loc, byte instrument, byte note); public void playNote(@NotNull Location loc, byte instrument, byte note);
/** /**
* Play a note for a player at a location. This requires a note block * Play a note for the player at a location. <br>
* at the particular location (as far as the client is concerned). This * This <i>will</i> work with cake.
* will not work without a note block. This will not work with cake. * <p>
* * This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}.
* @param loc The location of a note block * @param loc The location to play the note
* @param instrument The instrument * @param instrument The instrument
* @param note The note * @param note The note
*/ */
@ -469,6 +468,38 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/ */
public void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch); public void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch);
/**
* Play a sound for a player at the location. For sounds with multiple
* variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Location or Sound are null.
*
* @param location The location to play the sound
* @param sound The sound to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
public void playSound(@NotNull Location location, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/**
* Play a sound for a player at the location. For sounds with multiple
* variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Location or Sound are null. No sound
* will be heard by the player if their client does not have the respective
* sound for the value passed.
*
* @param location The location to play the sound
* @param sound The internal sound name to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
public void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/** /**
* Play a sound for a player at the location of the entity. * Play a sound for a player at the location of the entity.
* <p> * <p>
@ -519,6 +550,36 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/ */
public void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch); public void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch);
/**
* Play a sound for a player at the location of the entity. For sounds with
* multiple variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Entity or Sound are null.
*
* @param entity The entity to play the sound
* @param sound The sound to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
public void playSound(@NotNull Entity entity, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/**
* Play a sound for a player at the location of the entity. For sounds with
* multiple variations passing the same seed will always play the same variation.
* <p>
* This function will fail silently if Entity or Sound are null.
*
* @param entity The entity to play the sound
* @param sound The sound to play
* @param category The category of the sound
* @param volume The volume of the sound
* @param pitch The pitch of the sound
* @param seed The seed for the sound
*/
public void playSound(@NotNull Entity entity, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch, long seed);
/** /**
* Stop the specified sound from playing. * Stop the specified sound from playing.
* *