From 293a4d9ae2bdbe813579199193c05a10d90b6754 Mon Sep 17 00:00:00 2001 From: EvilSeph Date: Fri, 17 Jun 2011 03:00:49 -0400 Subject: [PATCH] Added Instrument enum, Note class and get/setNote functions. Thanks xZise! --- src/main/java/org/bukkit/Instrument.java | 34 +++ src/main/java/org/bukkit/Note.java | 202 ++++++++++++++++++ src/main/java/org/bukkit/block/NoteBlock.java | 39 +++- src/main/java/org/bukkit/entity/Player.java | 13 ++ 4 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/bukkit/Instrument.java create mode 100644 src/main/java/org/bukkit/Note.java diff --git a/src/main/java/org/bukkit/Instrument.java b/src/main/java/org/bukkit/Instrument.java new file mode 100644 index 00000000..e54d0a2a --- /dev/null +++ b/src/main/java/org/bukkit/Instrument.java @@ -0,0 +1,34 @@ +package org.bukkit; + +import java.util.HashMap; +import java.util.Map; + +public enum Instrument { + + PIANO((byte) 0x0), // All other + BASS_DRUM((byte) 0x1), // Stone + SNARE_DRUM((byte) 0x2), // Sand + STICKS((byte) 0x3), // Glass + BASS_GUITAR((byte) 0x4); // Wood + + private final byte type; + private final static Map types = new HashMap(); + + private Instrument(byte type) { + this.type = type; + } + + public byte getType() { + return this.type; + } + + public static Instrument getByType(final byte type) { + return types.get(type); + } + + static { + for (Instrument instrument : Instrument.values()) { + types.put(instrument.getType(), instrument); + } + } +} diff --git a/src/main/java/org/bukkit/Note.java b/src/main/java/org/bukkit/Note.java new file mode 100644 index 00000000..46ae79cc --- /dev/null +++ b/src/main/java/org/bukkit/Note.java @@ -0,0 +1,202 @@ +package org.bukkit; + +import java.util.HashMap; +import java.util.Map; + +/** + * A note class to store a specific note. + */ +public class Note { + + /** + * An enum holding tones. + */ + public enum Tone { + F((byte) -0x1, true), + G((byte) 0x1, true), + A((byte) 0x3, true), + B((byte) 0x5, false), + C((byte) 0x6, true), + D((byte) 0x8, true), + E((byte) 0xA, false); + + private final boolean sharpable; + private final byte id; + private static final Map tones = new HashMap(); + /** The number of tones including sharped tones. */ + public static final byte TONES_COUNT; + + private Tone(byte id, boolean sharpable) { + this.id = id; + this.sharpable = sharpable; + } + + /** + * Returns the not sharped id of this tone. + * + * @return the not sharped id of this tone. + */ + public byte getId() { + return getId(false); + } + + /** + * Returns the id of this tone. These method allows to return the + * sharped id of the tone. If the tone couldn't be sharped it always + * return the not sharped id of this tone. + * + * @param sharped + * Set to true to return the sharped id. + * @return the id of this tone. + */ + public byte getId(boolean sharped) { + byte tempId = (byte) (sharped && sharpable ? id + 1 : id); + + while (tempId < 0) { + tempId += TONES_COUNT; + } + return (byte) (tempId % TONES_COUNT); + } + + /** + * Returns if this tone could be sharped. + * + * @return if this tone could be sharped. + */ + public boolean getSharpable() { + return sharpable; + } + + /** + * Returns if this tone id is the sharped id of the tone. + * + * @param id + * the id of the tone. + * @return if the tone id is the sharped id of the tone. + * @throws IllegalArgumentException + * if neither the tone nor the semitone have the id. + */ + public boolean isSharped(byte id) { + byte toneId = getId(); + if (id == toneId) { + return false; + } else if (id == toneId + 1) { + return true; + } else { + // The id isn't matching to the tone! + throw new IllegalArgumentException("The id isn't matching to the tone."); + } + } + + /** + * Returns the tone to id. Also returning the semitones. + * + * @param id + * the id of the tone. + * @return the tone to id. + */ + public static Tone getToneById(byte id) { + return tones.get(id); + } + + static { + byte lowest = F.getId(); + byte highest = F.getId(); + for (Tone tone : Tone.values()) { + byte id = tone.getId(); + tones.put(id, tone); + if (id < lowest) { + lowest = id; + } + if (tone.getSharpable()) { + id++; + tones.put(id, tone); + } + if (id > highest) { + highest = id; + } + } + + TONES_COUNT = (byte) (highest - lowest + 1); + } + } + + private final byte note; + + /** + * Creates a new note. + * + * @param note + * Internal note id. {@link #getId()} always return this value. + * The value has to be in the interval [0; 24]. + */ + public Note(byte note) { + if (note < 0 || note > 24) { + throw new IllegalArgumentException("The note value has to be between 0 and 24."); + } + this.note = note; + } + + /** + * Creates a new note. + * + * @param octave + * The octave where the note is in. Has to be 0 - 2. + * @param note + * The tone within the octave. If the octave is 2 the note has to + * be F#. + * @param sharped + * Set it the tone is sharped (e.g. for F#). + */ + public Note(byte octave, Tone note, boolean sharped) { + if (sharped && !note.getSharpable()) { + throw new IllegalArgumentException("This tone could not be sharped."); + } + if (octave < 0 || octave > 2 || !(octave == 2 && note == Tone.F && sharped)) { + throw new IllegalArgumentException("The octave has to be F#0 - F#2"); + } + this.note = (byte) (octave * Tone.TONES_COUNT + note.getId(sharped)); + } + + /** + * Returns the internal id of this note. + * + * @return the internal id of this note. + */ + public byte getId() { + return note; + } + + /** + * Returns the octave of this note. + * + * @return the octave of this note. + */ + public int getOctave() { + return note / Tone.TONES_COUNT; + } + + private byte getToneByte() { + return (byte) (note % Tone.TONES_COUNT); + } + + /** + * Returns the tone of this note. + * + * @return the tone of this note. + */ + public Tone getTone() { + return Tone.getToneById(getToneByte()); + } + + /** + * Returns if this note is sharped. + * + * @return if this note is sharped. + */ + public boolean getSharped() { + byte note = getToneByte(); + return Tone.getToneById(note).isSharped(note); + } + +} diff --git a/src/main/java/org/bukkit/block/NoteBlock.java b/src/main/java/org/bukkit/block/NoteBlock.java index bc704c12..de71cb5e 100644 --- a/src/main/java/org/bukkit/block/NoteBlock.java +++ b/src/main/java/org/bukkit/block/NoteBlock.java @@ -1,11 +1,10 @@ package org.bukkit.block; -import org.bukkit.entity.Player; +import org.bukkit.Instrument; +import org.bukkit.Note; /** * Represents a note. - * - * @author sk89q */ public interface NoteBlock extends BlockState { @@ -13,15 +12,40 @@ public interface NoteBlock extends BlockState { * Gets the note. * * @return + * @deprecated use {@link #getRawNote()} instead */ + @Deprecated public byte getNote(); + /** + * Gets the note. + * + * @return + */ + public byte getRawNote(); + + /** + * Set the note. + * + * @param note + * @deprecated use {@link #setRawNote(byte)} instead + */ + @Deprecated + public void setNote(byte note); + /** * Set the note. * * @param note */ - public void setNote(byte note); + public void setNote(Note note); + + /** + * Set the note. + * + * @param note + */ + public void setRawNote(byte note); /** * Attempts to play the note at block
@@ -38,4 +62,11 @@ public interface NoteBlock extends BlockState { * @return true if successful, otherwise false */ public boolean play(byte instrument, byte note); + + /** + * Plays an arbitrary note with an arbitrary instrument + * + * @return true if successful, otherwise false + */ + public boolean play(Instrument instrument, Note note); } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index b51324d7..edce853c 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -3,8 +3,10 @@ package org.bukkit.entity; import java.net.InetSocketAddress; import org.bukkit.Achievement; import org.bukkit.Effect; +import org.bukkit.Instrument; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Note; import org.bukkit.Statistic; import org.bukkit.command.CommandSender; @@ -142,6 +144,17 @@ public interface Player extends HumanEntity, CommandSender { */ public void playNote(Location loc, byte instrument, byte note); + /** + * Play a note for a player at a location. This requires a note block + * at the particular location (as far as the client is concerned). This + * will not work without a note block. This will not work with cake. + * + * @param loc + * @param instrument + * @param note + */ + public void playNote(Location loc, Instrument instrument, Note note); + /** * Plays an effect to just this player. *