Files
Advenskalender/src/main/java/de/mviper/adventskalender/christmas/SantaMelody.java
T
2026-11-13 17:46:26 +00:00

74 lines
3.3 KiB
Java

package de.mviper.adventskalender.christmas;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.util.Collection;
import java.util.function.Supplier;
/** Spielt Weihnachtsmelodien mit Glocken (Notenblock-Klaenge, keine Dateien noetig). */
final class SantaMelody {
// Melodie: {Halbtoene ueber C4, Dauer in Achteln (1 = Achtel)}
private static final int[][] JINGLE = {
{4, 2}, {4, 2}, {4, 4}, {4, 2}, {4, 2}, {4, 4}, {4, 2}, {7, 2}, {0, 3}, {2, 1}, {4, 8},
{5, 2}, {5, 2}, {5, 3}, {5, 1}, {5, 2}, {4, 2}, {4, 2}, {4, 1}, {4, 1}, {4, 2}, {2, 2}, {2, 2}, {4, 2}, {2, 4}, {7, 4},
{4, 2}, {4, 2}, {4, 4}, {4, 2}, {4, 2}, {4, 4}, {4, 2}, {7, 2}, {0, 3}, {2, 1}, {4, 8},
{5, 2}, {5, 2}, {5, 3}, {5, 1}, {5, 2}, {4, 2}, {4, 2}, {4, 1}, {4, 1}, {7, 2}, {7, 2}, {5, 2}, {2, 2}, {0, 8},
};
// "We Wish You a Merry Christmas"
private static final int[][] WISH = {
{2, 2}, {7, 2}, {7, 1}, {9, 1}, {7, 1}, {6, 1}, {4, 2}, {4, 2}, {4, 2}, {9, 2}, {9, 1}, {11, 1}, {9, 1}, {7, 1},
{6, 2}, {2, 2}, {2, 2}, {11, 2}, {11, 1}, {12, 1}, {11, 1}, {9, 1}, {7, 2}, {4, 2}, {2, 1}, {2, 1}, {4, 2},
{9, 2}, {6, 2}, {7, 6},
};
static final int[][][] TUNES = {JINGLE, WISH};
private final ChristmasManager mgr;
private BukkitTask task;
SantaMelody(ChristmasManager mgr) { this.mgr = mgr; }
boolean playing() { return task != null; }
/** Santa-Event: Melodie fuer die Spieler der Welt (oder alle, santa.melody.everyone). */
void play(World world) {
if (!mgr.cfg().getBoolean("santa.melody.enable", true)) return;
final boolean everyone = mgr.cfg().getBoolean("santa.melody.everyone", false);
final float volume = (float) mgr.cfg().getDouble("santa.melody.volume", 1.0);
final int tempo = Math.max(1, mgr.cfg().getInt("santa.melody.tempo", 3));
play(() -> everyone ? Bukkit.getOnlinePlayers() : world.getPlayers(), 0, volume, tempo, null);
}
/** Spielt eine Melodie fuer ein sich aenderndes Publikum; done wird nach dem letzten Ton aufgerufen. */
void play(Supplier<Collection<? extends Player>> audience, int tune, float volume, int tempo, Runnable done) {
stop();
final int[][] notes = TUNES[Math.floorMod(tune, TUNES.length)];
final int[] pos = {0};
final int[] wait = {0};
task = Bukkit.getScheduler().runTaskTimer(mgr.plugin(), () -> {
if (wait[0]-- > 0) return;
if (pos[0] >= notes.length) {
stop();
if (done != null) done.run();
return;
}
int[] n = notes[pos[0]++];
float pitch = (float) Math.pow(2.0, (n[0] + 6 - 12) / 12.0); // C4 = Notenblock-Ton 6
for (Player p : audience.get()) {
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_BELL, SoundCategory.RECORDS, volume, pitch);
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.RECORDS, volume * 0.5f, pitch);
}
wait[0] = n[1] * tempo - 1;
}, 10L, 1L);
}
void stop() {
if (task != null) task.cancel();
task = null;
}
}