Note block player
This commit is contained in:
parent
cbafb2ba91
commit
488895ea53
131
Plugins/Mineplex.Core/src/mineplex/core/noteblock/NBSReader.java
Normal file
131
Plugins/Mineplex.Core/src/mineplex/core/noteblock/NBSReader.java
Normal file
@ -0,0 +1,131 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Information about the NBS Format was taken from
|
||||
* http://www.stuffbydavid.com/mcnbs/format
|
||||
*/
|
||||
public class NBSReader
|
||||
{
|
||||
public static NoteSong loadSong(String fileName) throws FileNotFoundException
|
||||
{
|
||||
return loadSong(new DataInputStream(new FileInputStream(new File(fileName))));
|
||||
}
|
||||
|
||||
public static NoteSong loadSong(DataInputStream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Header Information
|
||||
short length = readShort(stream);
|
||||
short height = readShort(stream);
|
||||
String name = readString(stream);
|
||||
String author = readString(stream);
|
||||
String originalAuthor = readString(stream);
|
||||
String description = readString(stream);
|
||||
short tempo = readShort(stream); // Tempo multiplied by 1000
|
||||
boolean autosave = stream.readBoolean();
|
||||
byte autosaveDuration = stream.readByte();
|
||||
byte timeSignature = stream.readByte();
|
||||
int minutesSpent = readInt(stream);
|
||||
int leftClicks = readInt(stream);
|
||||
int rightClicks = readInt(stream);
|
||||
int blocksAdded = readInt(stream);
|
||||
int blocksRemoved = readInt(stream);
|
||||
String midiFileName = readString(stream);
|
||||
|
||||
HashMap<Integer, NoteLayer> layerMap = new HashMap<Integer, NoteLayer>();
|
||||
|
||||
// Note Block Information
|
||||
int tick = -1;
|
||||
int jumps = 0;
|
||||
while (true)
|
||||
{
|
||||
jumps = readShort(stream);
|
||||
if (jumps == 0)
|
||||
break;
|
||||
tick += jumps;
|
||||
int layer = -1;
|
||||
while (true)
|
||||
{
|
||||
jumps = readShort(stream);
|
||||
if (jumps == 0)
|
||||
break;
|
||||
layer += jumps;
|
||||
byte instrument = stream.readByte();
|
||||
byte key = stream.readByte();
|
||||
|
||||
Note note = new Note(instrument, key);
|
||||
NoteLayer noteLayer = layerMap.get(layer);
|
||||
if (noteLayer == null)
|
||||
{
|
||||
noteLayer = new NoteLayer();
|
||||
layerMap.put(layer, noteLayer);
|
||||
}
|
||||
noteLayer.setNote(tick, note);
|
||||
}
|
||||
}
|
||||
|
||||
// Layer Information
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
NoteLayer layer = layerMap.get(i);
|
||||
if (layer != null)
|
||||
{
|
||||
layer.setName(readString(stream));
|
||||
layer.setVolume(stream.readByte());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("[NBSReader] Successfully loaded song " + name + "");
|
||||
System.out.println("Tempo: " + tempo);
|
||||
return new NoteSong(length, height, name, tempo, timeSignature, layerMap);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int readInt(DataInputStream stream) throws IOException
|
||||
{
|
||||
// For some reason the bytes are in reverse order from stream.readInt()
|
||||
int ch1 = stream.read();
|
||||
int ch2 = stream.read();
|
||||
int ch3 = stream.read();
|
||||
int ch4 = stream.read();
|
||||
if ((ch1 | ch2 | ch3 | ch4) < 0)
|
||||
throw new EOFException();
|
||||
return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1);
|
||||
}
|
||||
|
||||
private static short readShort(DataInputStream stream) throws IOException
|
||||
{
|
||||
// For some reason the bytes are in reverse order from stream.readShort()
|
||||
int ch1 = stream.read();
|
||||
int ch2 = stream.read();
|
||||
if ((ch1 | ch2) < 0)
|
||||
throw new EOFException();
|
||||
return (short)((ch2 << 8) + ch1);
|
||||
}
|
||||
|
||||
private static String readString(DataInputStream stream) throws IOException
|
||||
{
|
||||
int length = readInt(stream);
|
||||
char[] string = new char[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
string[i] = (char) stream.readByte();
|
||||
}
|
||||
return new String(string);
|
||||
}
|
||||
}
|
26
Plugins/Mineplex.Core/src/mineplex/core/noteblock/Note.java
Normal file
26
Plugins/Mineplex.Core/src/mineplex/core/noteblock/Note.java
Normal file
@ -0,0 +1,26 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
/**
|
||||
* Represents a single note to be played
|
||||
*/
|
||||
public class Note
|
||||
{
|
||||
private byte _instrument;
|
||||
private byte _note;
|
||||
|
||||
public Note(byte instrument, byte note)
|
||||
{
|
||||
_instrument = instrument;
|
||||
_note = note;
|
||||
}
|
||||
|
||||
public byte getInstrument()
|
||||
{
|
||||
return _instrument;
|
||||
}
|
||||
|
||||
public byte getNote()
|
||||
{
|
||||
return _note;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Represents a layer of notes in Note Block Studio
|
||||
*/
|
||||
public class NoteLayer
|
||||
{
|
||||
private HashMap<Integer, Note> _noteMap; // Notes indexed by ticks
|
||||
private int _volume; // Volume as a percentage 1-100
|
||||
private String _name;
|
||||
|
||||
public NoteLayer()
|
||||
{
|
||||
_noteMap = new HashMap<Integer, Note>();
|
||||
_volume = 100;
|
||||
_name = "";
|
||||
}
|
||||
|
||||
public int getVolume()
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
|
||||
public void setVolume(int volume)
|
||||
{
|
||||
_volume = volume;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void setNote(int ticks, Note note)
|
||||
{
|
||||
_noteMap.put(ticks, note);
|
||||
}
|
||||
|
||||
public Note getNote(int ticks)
|
||||
{
|
||||
return _noteMap.get(ticks);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
|
||||
public class NotePlayer
|
||||
{
|
||||
private final NoteSong _song;
|
||||
private final long _sleepMs;
|
||||
private volatile boolean _loop;
|
||||
private volatile int _tick;
|
||||
private volatile boolean _finished;
|
||||
|
||||
public NotePlayer(NoteSong song, boolean loop)
|
||||
{
|
||||
_song = song;
|
||||
_sleepMs = (long) (1000 / (song.getTempo() / 100D));
|
||||
_loop = loop;
|
||||
_tick = 0;
|
||||
_finished = false;
|
||||
|
||||
startThread();
|
||||
}
|
||||
|
||||
private void startThread()
|
||||
{
|
||||
Thread thread = new Thread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (!_finished)
|
||||
{
|
||||
_tick++;
|
||||
if (_tick > _song.getLength())
|
||||
{
|
||||
if (_loop)
|
||||
{
|
||||
_tick = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_finished = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playTick(_tick);
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(_sleepMs);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void playTick(int tick)
|
||||
{
|
||||
for (NoteLayer layer : _song.getLayers())
|
||||
{
|
||||
Note note = layer.getNote(tick);
|
||||
if (note != null)
|
||||
{
|
||||
float volume = layer.getVolume() / 100F;
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
player.playSound(player.getEyeLocation(), UtilNote.getInstrumentSound(note.getInstrument()), volume, (float) UtilNote.getPitch(note.getNote() - 33));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel()
|
||||
{
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class NoteSong
|
||||
{
|
||||
// Song Data
|
||||
private short _length;
|
||||
private short _height;
|
||||
private String _name;
|
||||
private short _tempo;
|
||||
private byte _timeSignature;
|
||||
|
||||
// Layer Data
|
||||
private HashMap<Integer, NoteLayer> _layerMap;
|
||||
|
||||
public NoteSong(short length, short height, String name, short tempo, byte timeSignature, HashMap<Integer, NoteLayer> layerMap)
|
||||
{
|
||||
_length = length;
|
||||
_height = height;
|
||||
_name = name;
|
||||
_tempo = tempo;
|
||||
_timeSignature = timeSignature;
|
||||
_layerMap = layerMap;
|
||||
}
|
||||
|
||||
public short getLength()
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
public short getHeight()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public short getTempo()
|
||||
{
|
||||
return _tempo;
|
||||
}
|
||||
|
||||
public byte getTimeSignature()
|
||||
{
|
||||
return _timeSignature;
|
||||
}
|
||||
|
||||
public Collection<NoteLayer> getLayers()
|
||||
{
|
||||
return _layerMap.values();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package mineplex.core.noteblock;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
|
||||
/**
|
||||
* See http://minecraft.gamepedia.com/Note_Block for information about pitches
|
||||
*/
|
||||
public class UtilNote
|
||||
{
|
||||
private static final double[] PITCH = { 0.5, 0.53, 0.56, 0.6, 0.63, 0.67, 0.7, 0.76, 0.8, 0.84, 0.9, 0.94, 1.0,
|
||||
1.06, 1.12, 1.18, 1.26, 1.34, 1.42, 1.5, 1.6, 1.68, 1.78, 1.88, 2.0 };
|
||||
|
||||
public static Sound getInstrumentSound(byte instrument)
|
||||
{
|
||||
switch (instrument)
|
||||
{
|
||||
case 0:
|
||||
return Sound.NOTE_PIANO;
|
||||
case 1:
|
||||
return Sound.NOTE_BASS_GUITAR;
|
||||
case 2:
|
||||
return Sound.NOTE_BASS_DRUM;
|
||||
case 3:
|
||||
return Sound.NOTE_SNARE_DRUM;
|
||||
case 4:
|
||||
return Sound.NOTE_STICKS;
|
||||
default:
|
||||
return Sound.NOTE_PIANO;
|
||||
}
|
||||
}
|
||||
|
||||
public static double getPitch(int note)
|
||||
{
|
||||
if (note >= 0 && note < PITCH.length)
|
||||
{
|
||||
return PITCH[note];
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package mineplex.hub;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -34,6 +35,9 @@ import mineplex.core.hologram.HologramManager;
|
||||
import mineplex.core.inventory.InventoryManager;
|
||||
import mineplex.core.message.PrivateMessageEvent;
|
||||
import mineplex.core.mount.MountManager;
|
||||
import mineplex.core.noteblock.NBSReader;
|
||||
import mineplex.core.noteblock.NotePlayer;
|
||||
import mineplex.core.noteblock.NoteSong;
|
||||
import mineplex.core.notifier.NotificationManager;
|
||||
import mineplex.core.npc.NpcManager;
|
||||
import mineplex.core.packethandler.PacketHandler;
|
||||
@ -219,7 +223,6 @@ public class HubManager extends MiniClientPlugin<HubClient>
|
||||
|
||||
((CraftWorld)Bukkit.getWorlds().get(0)).getHandle().pvpMode = true;
|
||||
|
||||
|
||||
new BonusManager(plugin, clientManager, serverStatusManager, donationManager, pollManager , npcManager, hologramManager, statsManager, _inventoryManager, petManager, giveawayManager);
|
||||
|
||||
// _halloweenManager = new HalloweenSpookinessManager(this);
|
||||
@ -229,6 +232,20 @@ public class HubManager extends MiniClientPlugin<HubClient>
|
||||
|
||||
_serverName = getPlugin().getConfig().getString("serverstatus.name");
|
||||
_serverName = _serverName.substring(0, Math.min(16, _serverName.length()));
|
||||
|
||||
// try
|
||||
// {
|
||||
// NoteSong song = NBSReader.loadSong("songs/LetItGo.nbs");
|
||||
// if (song != null)
|
||||
// {
|
||||
// NotePlayer player = new NotePlayer(song, true);
|
||||
// }
|
||||
// }
|
||||
// catch (FileNotFoundException e)
|
||||
// {
|
||||
// e.printStackTrace();
|
||||
// System.out.println("FAILED TO LOAD SONG!!");
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user