mirror of
https://code.chipmunk.land/ChomeNS/chipmunkmod.git
synced 2025-11-13 21:06:16 +00:00
refactor: improve a lot of stuff about music, and also stereo support for NBS
This commit is contained in:
parent
11d89993b2
commit
1034518f5f
7 changed files with 101 additions and 49 deletions
|
|
@ -220,7 +220,7 @@ public class MusicCommand {
|
|||
mergedList.addAll(files);
|
||||
final Component component = Component.translatable("Songs - %s", Component.join(JoinConfiguration.separator(Component.space()), mergedList)).color(NamedTextColor.GREEN);
|
||||
|
||||
((Audience) MinecraftClient.getInstance().player).sendMessage(component);
|
||||
MinecraftClient.getInstance().player.sendMessage(component);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import land.chipmunk.chipmunkmod.song.Song;
|
|||
import land.chipmunk.chipmunkmod.song.SongLoaderException;
|
||||
import land.chipmunk.chipmunkmod.song.SongLoaderThread;
|
||||
import land.chipmunk.chipmunkmod.util.MathUtilities;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
|
@ -14,7 +14,6 @@ import net.minecraft.client.network.ClientPlayNetworkHandler;
|
|||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -55,35 +54,42 @@ public class SongPlayer {
|
|||
// TODO: Less duplicate code
|
||||
|
||||
public void loadSong (Path location) {
|
||||
final ClientPlayerEntity player = client.player;
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
if (loaderThread != null) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Already loading a song, cannot load another", NamedTextColor.RED));
|
||||
player.sendMessage(Component.translatable("Already loading a song, cannot load another", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final SongLoaderThread _loaderThread = new SongLoaderThread(location);
|
||||
((Audience) client.player).sendMessage(Component.translatable("Loading %s", Component.text(location.getFileName().toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
_loaderThread.start();
|
||||
loaderThread = _loaderThread;
|
||||
loaderThread = new SongLoaderThread(location);
|
||||
player.sendMessage(Component.translatable("Loading %s", Component.text(location.getFileName().toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
loaderThread.start();
|
||||
} catch (SongLoaderException e) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Failed to load song: %s", e.message.getString()).color(NamedTextColor.RED));
|
||||
player.sendMessage(Component.translatable("Failed to load song: %s", e.message.getString()).color(NamedTextColor.RED));
|
||||
loaderThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSong (URL location) {
|
||||
final ClientPlayerEntity player = client.player;
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
if (loaderThread != null) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Already loading a song, cannot load another", NamedTextColor.RED));
|
||||
player.sendMessage(Component.translatable("Already loading a song, cannot load another", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final SongLoaderThread _loaderThread = new SongLoaderThread(location);
|
||||
((Audience) client.player).sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
player.sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
_loaderThread.start();
|
||||
loaderThread = _loaderThread;
|
||||
} catch (SongLoaderException e) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Failed to load song: %s", e.message.getString()).color(NamedTextColor.RED));
|
||||
player.sendMessage(Component.translatable("Failed to load song: %s", e.message.getString()).color(NamedTextColor.RED));
|
||||
loaderThread = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -101,12 +107,12 @@ public class SongPlayer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (loaderThread != null && !loaderThread.isAlive()) {
|
||||
if (loaderThread != null && !loaderThread.isAlive() && client.player != null) {
|
||||
if (loaderThread.exception != null) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Failed to load song: %s", loaderThread.exception.message.getString()).color(NamedTextColor.RED));
|
||||
client.player.sendMessage(Component.translatable("Failed to load song: %s", loaderThread.exception.message.getString()).color(NamedTextColor.RED));
|
||||
} else {
|
||||
songQueue.add(loaderThread.song);
|
||||
((Audience) client.player).sendMessage(Component.translatable("Added %s to the song queue", Component.empty().append(loaderThread.song.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
client.player.sendMessage(Component.translatable("Added %s to the song queue", Component.empty().append(loaderThread.song.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
}
|
||||
loaderThread = null;
|
||||
}
|
||||
|
|
@ -115,7 +121,16 @@ public class SongPlayer {
|
|||
if (songQueue.isEmpty()) return;
|
||||
|
||||
currentSong = songQueue.poll();
|
||||
((Audience) client.player).sendMessage(Component.translatable("Now playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
if (client.player != null) client.player.sendMessage(
|
||||
Component
|
||||
.translatable(
|
||||
"Now playing %s",
|
||||
Component.empty()
|
||||
.append(currentSong.name)
|
||||
.color(NamedTextColor.DARK_GREEN)
|
||||
)
|
||||
.color(NamedTextColor.GREEN)
|
||||
);
|
||||
currentSong.play();
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +138,7 @@ public class SongPlayer {
|
|||
else ticksUntilPausedActionbar = 20;
|
||||
|
||||
try {
|
||||
if (!useCore && actionbar && client.player != null) ((Audience) client.player).sendActionBar(generateActionbar());
|
||||
if (!useCore && actionbar && client.player != null) client.player.sendActionBar(generateActionbar());
|
||||
else if (actionbar) CommandCore.INSTANCE.run("title " + SELECTOR + " actionbar " + GsonComponentSerializer.gson().serialize(generateActionbar()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
@ -134,7 +149,7 @@ public class SongPlayer {
|
|||
handlePlaying();
|
||||
|
||||
if (currentSong.finished()) {
|
||||
((Audience) client.player).sendMessage(Component.translatable("Finished playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
if (client.player != null) client.player.sendMessage(Component.translatable("Finished playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
|
||||
currentSong = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,24 +226,37 @@ public class SongPlayer {
|
|||
if (!useCore && client.player != null) {
|
||||
final float floatingPitch = (float) (0.5 * (Math.pow(2, ((note.pitch + (pitch / 10)) / 12))));
|
||||
|
||||
final String[] thing = note.instrument.sound.split(":");
|
||||
|
||||
if (thing[1] == null) return; // idk if this can be null but ill just protect it for now i guess
|
||||
final String sound = note.instrument.sound;
|
||||
|
||||
client.submit(() -> client.world.playSound(
|
||||
client.player.getX(),
|
||||
client.player.getY(),
|
||||
client.player.getZ(),
|
||||
SoundEvent.of(Identifier.of(thing[0], thing[1])),
|
||||
client.player.getX() + note.position.getX(),
|
||||
client.player.getY() + note.position.getY(),
|
||||
client.player.getZ() + note.position.getZ(),
|
||||
SoundEvent.of(Identifier.of(Key.MINECRAFT_NAMESPACE, sound)),
|
||||
SoundCategory.RECORDS,
|
||||
note.volume,
|
||||
floatingPitch,
|
||||
true
|
||||
));
|
||||
} else {
|
||||
final float floatingPitch = MathUtilities.clamp((float) (0.5 * (Math.pow(2, ((note.pitch + (pitch / 10)) / 12)))), 0F, 2F);
|
||||
final double floatingPitch = MathUtilities.clamp(0.5 * (Math.pow(2, ((note.pitch + (pitch / 10)) / 12))), 0F, 2F);
|
||||
|
||||
CommandCore.INSTANCE.run("execute as " + SELECTOR + " at @s run playsound " + note.instrument.sound + " record @s ~ ~ ~ " + note.volume + " " + floatingPitch);
|
||||
CommandCore.INSTANCE.run(
|
||||
String.format(
|
||||
"execute as %s at @s run playsound %s record @s ^%f ^%f ^%f %f %f",
|
||||
|
||||
SELECTOR,
|
||||
|
||||
note.instrument.sound,
|
||||
|
||||
note.position.getX(),
|
||||
note.position.getY(),
|
||||
note.position.getZ(),
|
||||
|
||||
note.volume,
|
||||
floatingPitch
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -34,16 +34,16 @@ public class Instrument {
|
|||
this.id = id;
|
||||
this.name = name;
|
||||
this.offset = offset;
|
||||
this.sound = "minecraft:block.note_block." + name;
|
||||
this.sound = "block.note_block." + name;
|
||||
}
|
||||
|
||||
public static Instrument of(String sound) {
|
||||
return new Instrument(-1, null, 0, sound);
|
||||
}
|
||||
|
||||
private static Instrument[] values = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING};
|
||||
private static final Instrument[] VALUES = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING};
|
||||
|
||||
public static Instrument fromId(int id) {
|
||||
return values[id];
|
||||
return VALUES[id];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package land.chipmunk.chipmunkmod.song;
|
||||
|
||||
import land.chipmunk.chipmunkmod.util.DownloadUtilities;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
|
@ -143,7 +144,7 @@ public class MidiConverter {
|
|||
float volume = (float) velocity / 127.0f;
|
||||
long time = microTime / 1000L;
|
||||
|
||||
return new Note(instrument, pitch, volume, time);
|
||||
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
|
||||
}
|
||||
|
||||
private static Note getMidiPercussionNote(int midiPitch, int velocity, long microTime) {
|
||||
|
|
@ -154,7 +155,7 @@ public class MidiConverter {
|
|||
Instrument instrument = Instrument.fromId(noteId / 25);
|
||||
long time = microTime / 1000L;
|
||||
|
||||
return new Note(instrument, pitch, volume, time);
|
||||
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package land.chipmunk.chipmunkmod.song;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
|
@ -156,15 +158,20 @@ public class NBSConverter {
|
|||
}
|
||||
for (NBSNote note : nbsNotes) {
|
||||
Instrument instrument;
|
||||
int key = note.key;
|
||||
double key;
|
||||
if (note.instrument < instrumentIndex.length) {
|
||||
instrument = instrumentIndex[note.instrument];
|
||||
|
||||
key = (double) ((note.key * 100) + note.pitch) / 100;
|
||||
} else {
|
||||
int index = note.instrument - instrumentIndex.length;
|
||||
|
||||
if (index >= customInstruments.size()) continue;
|
||||
|
||||
NBSCustomInstrument customInstrument = customInstruments.get(index);
|
||||
instrument = Instrument.of(customInstrument.name);
|
||||
key += customInstrument.pitch;
|
||||
|
||||
key = (note.key) + (customInstrument.pitch + (double) note.pitch / 100);
|
||||
}
|
||||
|
||||
byte layerVolume = 100;
|
||||
|
|
@ -172,8 +179,29 @@ public class NBSConverter {
|
|||
layerVolume = nbsLayers.get(note.layer).volume;
|
||||
}
|
||||
|
||||
int pitch = key - 33;
|
||||
song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo)));
|
||||
while (key < 33) key += 12;
|
||||
while (key > 57) key -= 12;
|
||||
|
||||
double pitch = key - 33;
|
||||
|
||||
final int layerStereo = Byte.toUnsignedInt(nbsLayers.get(note.layer).stereo);
|
||||
final int notePanning = Byte.toUnsignedInt(note.panning);
|
||||
|
||||
double value;
|
||||
|
||||
if (layerStereo == 100 && notePanning != 100) value = notePanning;
|
||||
else if (notePanning == 100 && layerStereo != 100) value = layerStereo;
|
||||
else value = (double) (layerStereo + notePanning) / 2;
|
||||
|
||||
double x;
|
||||
|
||||
if (value > 100) x = (value - 100) / -100;
|
||||
else if (value == 100) x = 0;
|
||||
else x = ((value - 100) * -1) / 100;
|
||||
|
||||
final Vec3d position = new Vec3d(x, 0 ,0);
|
||||
|
||||
song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), position));
|
||||
}
|
||||
|
||||
song.length = song.get(song.size() - 1).time + 50;
|
||||
|
|
|
|||
|
|
@ -1,31 +1,25 @@
|
|||
package land.chipmunk.chipmunkmod.song;
|
||||
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class Note implements Comparable<Note> {
|
||||
public Instrument instrument;
|
||||
public int pitch;
|
||||
public double pitch;
|
||||
public float volume;
|
||||
public long time;
|
||||
public Vec3d position;
|
||||
|
||||
public Note(Instrument instrument, int pitch, float volume, long time) {
|
||||
public Note(Instrument instrument, double pitch, float volume, long time, Vec3d position) {
|
||||
this.instrument = instrument;
|
||||
this.pitch = pitch;
|
||||
this.volume = volume;
|
||||
this.time = time;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Note other) {
|
||||
if (time < other.time) {
|
||||
return -1;
|
||||
} else if (time > other.time) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int noteId() {
|
||||
return pitch + instrument.id * 25;
|
||||
return Long.compare(time, other.time);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ public class SongLoaderThread extends Thread {
|
|||
try {
|
||||
song = NBSConverter.getSongFromBytes(bytes, name);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue