From a5967874d2d92737ba198bab1bb520df83b8a9cf Mon Sep 17 00:00:00 2001 From: strictpvp Date: Sun, 9 Feb 2025 21:54:38 +0900 Subject: [PATCH 1/3] update to 1.21.4 --- build.gradle | 10 +- gradle.properties | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../xyz/nat1an/notebot/ModRegistries.java | 40 +++ remappedSrc/xyz/nat1an/notebot/Notebot.java | 35 +++ .../xyz/nat1an/notebot/NotebotPlayer.java | 287 +++++++++++++++++ .../notebot/commands/NotebotInfoCommand.java | 68 +++++ .../notebot/commands/NotebotStartCommand.java | 38 +++ .../notebot/commands/NotebotStopCommand.java | 35 +++ .../queue/NotebotQueueAddCommand.java | 47 +++ .../queue/NotebotQueueCleanCommand.java | 44 +++ .../commands/queue/NotebotQueueCommand.java | 49 +++ .../queue/NotebotQueueRemoveCommand.java | 56 ++++ .../suggestions/QueueSuggestionProvider.java | 33 ++ .../suggestions/SongSuggestionProvider.java | 59 ++++ .../xyz/nat1an/notebot/types/Note.java | 33 ++ .../xyz/nat1an/notebot/types/Song.java | 37 +++ .../notebot/utils/NotebotFileManager.java | 52 ++++ .../nat1an/notebot/utils/NotebotUtils.java | 289 ++++++++++++++++++ .../xyz/nat1an/notebot/NotebotPlayer.java | 68 ++--- .../notebot/commands/NotebotInfoCommand.java | 6 +- .../queue/NotebotQueueAddCommand.java | 3 +- .../queue/NotebotQueueCleanCommand.java | 3 +- .../commands/queue/NotebotQueueCommand.java | 2 +- .../queue/NotebotQueueRemoveCommand.java | 4 +- .../nat1an/notebot/utils/NotebotUtils.java | 40 +-- 26 files changed, 1276 insertions(+), 72 deletions(-) create mode 100644 remappedSrc/xyz/nat1an/notebot/ModRegistries.java create mode 100644 remappedSrc/xyz/nat1an/notebot/Notebot.java create mode 100644 remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java create mode 100644 remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java create mode 100644 remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java create mode 100644 remappedSrc/xyz/nat1an/notebot/types/Note.java create mode 100644 remappedSrc/xyz/nat1an/notebot/types/Song.java create mode 100644 remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java create mode 100644 remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java diff --git a/build.gradle b/build.gradle index 89308cb..52930c7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ plugins { - id 'fabric-loom' version '1.1-SNAPSHOT' + id 'fabric-loom' version '1.9-SNAPSHOT' id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 archivesBaseName = project.archives_base_name version = project.mod_version @@ -42,8 +42,8 @@ processResources { } tasks.withType(JavaCompile).configureEach { - // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. - it.options.release = 17 + // Minecraft 1.20.5 upwards uses Java 21. + it.options.release = 21 } java { diff --git a/gradle.properties b/gradle.properties index e13622a..c87256e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,13 +3,13 @@ org.gradle.jvmargs=-Xmx1G org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.20.1 - yarn_mappings=1.20.1+build.2 - loader_version=0.14.21 + minecraft_version=1.21.4 + yarn_mappings=1.21.4+build.8 + loader_version=0.16.9 # Mod Properties mod_version=1.1.1 maven_group=xyz.nat1an archives_base_name=notebot # Dependencies - fabric_version=0.83.1+1.20.1 + fabric_version=0.115.1+1.21.4 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fc10b60..9bf7bd3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/remappedSrc/xyz/nat1an/notebot/ModRegistries.java b/remappedSrc/xyz/nat1an/notebot/ModRegistries.java new file mode 100644 index 0000000..03b3179 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/ModRegistries.java @@ -0,0 +1,40 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot; + +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import xyz.nat1an.notebot.commands.NotebotInfoCommand; +import xyz.nat1an.notebot.commands.NotebotStartCommand; +import xyz.nat1an.notebot.commands.NotebotStopCommand; +import xyz.nat1an.notebot.commands.queue.NotebotQueueAddCommand; +import xyz.nat1an.notebot.commands.queue.NotebotQueueCleanCommand; +import xyz.nat1an.notebot.commands.queue.NotebotQueueCommand; +import xyz.nat1an.notebot.commands.queue.NotebotQueueRemoveCommand; + +public class ModRegistries { + public static void registerModStuff() { + ModRegistries.registerCommands(); + ModRegistries.registerEvents(); + } + + private static void registerCommands() { + ClientCommandRegistrationCallback.EVENT.register(NotebotInfoCommand::register); + ClientCommandRegistrationCallback.EVENT.register(NotebotStartCommand::register); + ClientCommandRegistrationCallback.EVENT.register(NotebotStopCommand::register); + + ClientCommandRegistrationCallback.EVENT.register(NotebotQueueCleanCommand::register); + ClientCommandRegistrationCallback.EVENT.register(NotebotQueueAddCommand::register); + ClientCommandRegistrationCallback.EVENT.register(NotebotQueueRemoveCommand::register); + ClientCommandRegistrationCallback.EVENT.register(NotebotQueueCommand::register); + } + + private static void registerEvents() { + ClientTickEvents.END_CLIENT_TICK.register(NotebotPlayer::onTick); + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/Notebot.java b/remappedSrc/xyz/nat1an/notebot/Notebot.java new file mode 100644 index 0000000..01ec093 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/Notebot.java @@ -0,0 +1,35 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot; + +import net.fabricmc.api.ModInitializer; +import net.minecraft.client.MinecraftClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import xyz.nat1an.notebot.utils.NotebotFileManager; + +public class Notebot implements ModInitializer { + // This logger is used to write text to the console and the log file. + // It is considered best practice to use your mod id as the logger's name. + // That way, it's clear which mod wrote info, warnings, and errors. + public static final Logger LOGGER = LoggerFactory.getLogger("notebot"); + public static final MinecraftClient mc = MinecraftClient.getInstance(); + + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + LOGGER.info("Hello Fabric world!"); + + NotebotFileManager.init(); + + ModRegistries.registerModStuff(); + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java b/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java new file mode 100644 index 0000000..0584796 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java @@ -0,0 +1,287 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot; + +import net.minecraft.block.Block; +import net.minecraft.block.NoteBlock; +import net.minecraft.block.enums.Instrument; +import net.minecraft.client.MinecraftClient; +import net.minecraft.registry.Registries; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import xyz.nat1an.notebot.types.Note; +import xyz.nat1an.notebot.types.Song; +import xyz.nat1an.notebot.utils.NotebotFileManager; +import xyz.nat1an.notebot.utils.NotebotUtils; + +import java.util.*; +import java.util.Map.Entry; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotPlayer { + /* Status */ + public static boolean playing = false; + + /* Some settings */ + public static boolean loop = false; + + /* The loaded song */ + public static Song song; + public static List trail = new ArrayList<>(); + public static List queue = new ArrayList<>(); + + /* Map of noteblocks and their pitch around the player [blockpos:pitch] */ + private static Map blockPitches = new HashMap<>(); + private static int timer = -10; + private static int tuneDelay = 0; + + public static int getNote(BlockPos pos) { + if (!isNoteblock(pos)) return -1; + + return mc.world.getBlockState(pos).get(NoteBlock.NOTE); + } + + public static void playBlock(BlockPos pos) { + if (!isNoteblock(pos)) return; + + mc.interactionManager.attackBlock(pos, Direction.UP); + mc.player.swingHand(Hand.MAIN_HAND); + } +/* + public static Instrument getInstrument(BlockPos pos) { + if (!isNoteblock(pos)) return Instrument.HARP; + return mc.world.getBlockState(pos).get(NoteBlock.INSTRUMENT); + } +*/ + public static Instrument getInstrumentUnderneath(BlockPos pos) { + if (!isNoteblock(pos)) return Instrument.HARP; + + // Retrieve the block underneath + BlockPos posUnderneath = pos.down(); + Block blockUnderneath = mc.world.getBlockState(posUnderneath).getBlock(); + + // Return the instrument associated with the block underneath + return blockToInstrument(blockUnderneath); + } + + public static Instrument blockToInstrument(Block block) { + + // Specific block checks + Identifier blockId = Registries.BLOCK.getId(block); + String blockIdString = blockId.toString(); + Instrument instrument = Instrument.HARP; // Default to Harp for any other block + + + if (blockIdString.equals("minecraft:dirt" ) || blockIdString.equals("minecraft:air")) { + return Instrument.HARP; + } else if (blockIdString.equals("minecraft:clay")) { + return Instrument.FLUTE; + } else if (blockIdString.equals("minecraft:gold_block")) { + return Instrument.BELL; + } else if (blockIdString.equals("minecraft:packed_ice")) { + return Instrument.CHIME; + } else if (blockIdString.equals("minecraft:bone_block")) { + return Instrument.XYLOPHONE; + } else if (blockIdString.equals("minecraft:iron_block")) { + return Instrument.IRON_XYLOPHONE; + } else if (blockIdString.equals("minecraft:soul_sand")) { + return Instrument.COW_BELL; + } else if (blockIdString.equals("minecraft:pumpkin")) { + return Instrument.DIDGERIDOO; + } else if (blockIdString.equals("minecraft:emerald_block")) { + return Instrument.BIT; + } else if (blockIdString.equals("minecraft:hay_block")) { + return Instrument.BANJO; + } else if (blockIdString.equals("minecraft:glowstone")) { + return Instrument.PLING; + } else if (blockIdString.equals("minecraft:sand") || blockIdString.equals("minecraft:gravel") || blockIdString.equals("minecraft:concrete_powder")) { + return Instrument.SNARE; + } else if (Arrays.asList("minecraft:stone", "minecraft:cobblestone", "minecraft:blackstone", "minecraft:netherrack", "minecraft:nylium", "minecraft:obsidian", + "minecraft:quartz", "minecraft:sandstone", "minecraft:ores", "minecraft:bricks", "minecraft:corals", + "minecraft:respawn_anchor", "minecraft:bedrock", "minecraft:concrete").contains(blockIdString)) { + return Instrument.BASEDRUM; + } else if (blockIdString.equals("minecraft:glass")) { + return Instrument.HAT; + } + + + BlockSoundGroup material = block.getDefaultState().getSoundGroup(); + + // Check for blocks with specific materials + if (material.equals(BlockSoundGroup.WOOD)) { + return Instrument.BASS; + } + if (material.equals(BlockSoundGroup.WOOL)) { + return Instrument.GUITAR; + } + if (material.equals(BlockSoundGroup.GLASS)) { + return Instrument.HAT; + } + if (material.equals(BlockSoundGroup.STONE)) { + return Instrument.BASEDRUM; + } + + + + return instrument; + } + + public static boolean isNoteblock(BlockPos pos) { + // Checks if this block is a noteblock and the noteblock can be played + return mc.world.getBlockState(pos).getBlock() instanceof NoteBlock && mc.world.getBlockState(pos.up()).isAir(); + } + + public static void stop() { + playing = false; + song = null; + blockPitches.clear(); + timer = -10; + tuneDelay = 0; + } + + public static boolean loadSong() { + blockPitches.clear(); + + try { + if (!mc.interactionManager.getCurrentGameMode().isSurvivalLike()) { + mc.player.sendMessage(Text.literal("§cNot in Survival mode!")); + + return false; + } else if (song == null) { + mc.player.sendMessage(Text.literal("§6No song in queue!, Use §c/notebot queue add §6to add a song.")); + + return false; + } + } catch (NullPointerException e) { + return false; + } + + timer = -10; + + BlockPos playerEyePos = new BlockPos((int) mc.player.getEyePos().x, (int) mc.player.getEyePos().y, (int) mc.player.getEyePos().z); + + List noteblocks = BlockPos.streamOutwards( + playerEyePos, 5, 5, 5 + ).filter( + NotebotPlayer::isNoteblock).map(BlockPos::toImmutable + ).toList(); + + HashMap requiredInstruments = new HashMap<>(); + HashMap foundInstruments = new HashMap<>(); + + for (Note note : song.requirements) { + Instrument instrument = Instrument.values()[note.instrument]; + requiredInstruments.put(instrument, requiredInstruments.getOrDefault(instrument, 0) + 1); + for (BlockPos pos : noteblocks) { + if (blockPitches.containsKey(pos)) continue; + + Instrument blockInstrument = getInstrumentUnderneath(pos); + if (note.instrument == blockInstrument.ordinal() && blockPitches.entrySet().stream().filter(e -> e.getValue() == note.pitch).noneMatch(e -> getInstrumentUnderneath(e.getKey()).ordinal() == blockInstrument.ordinal())) { + blockPitches.put(pos, note.pitch); + foundInstruments.put(blockInstrument, foundInstruments.getOrDefault(blockInstrument, 0) + 1); + break; + } + } + } + + for (Instrument instrument : requiredInstruments.keySet()) { + int requiredCount = requiredInstruments.get(instrument); + int foundCount = foundInstruments.getOrDefault(instrument, 0); + int missingCount = requiredCount - foundCount; + + if (missingCount > 0) { + mc.player.sendMessage(Text.literal("§6Warning: Missing §c" + missingCount + " §6" + instrument + " Noteblocks")); + } + } + + return true; + } + + public static void onTick(MinecraftClient client) { + if (!playing) return; + + if (song == null) { + if (queue.isEmpty()) { + mc.player.sendMessage(Text.literal("§cYou have no songs in your queue!")); + stop(); + return; + } + + NotebotPlayer.song = NotebotUtils.parse( + NotebotFileManager.getDir().resolve( + "songs/" + NotebotPlayer.queue.remove(0) + ) + ); + + loadSong(); + } + + // Tune Noteblocks + for (Entry e : blockPitches.entrySet()) { + int note = getNote(e.getKey()); + if (note == -1) + continue; + + if (note != e.getValue()) { + if (tuneDelay < 5) { + tuneDelay++; + return; + } + + int neededNote = e.getValue() < note ? e.getValue() + 25 : e.getValue(); + int reqTunes = Math.min(25, neededNote - note); + for (int i = 0; i < reqTunes; i++) + mc.interactionManager.interactBlock(mc.player, + Hand.MAIN_HAND, new BlockHitResult(Vec3d.ofCenter(e.getKey(), 1), Direction.UP, e.getKey(), true)); + + tuneDelay = 0; + + return; + } + } + + // Loop + if (timer - 10 > song.length) { + if (loop) { + timer = -10; + } else if (!queue.isEmpty()) { + song = null; + return; + } else { + mc.player.sendMessage(Text.literal("§6The queue is empty, stopping...")); + stop(); + return; + } + } + + if (timer == -10) { + mc.player.sendMessage(Text.literal("§6Now Playing: §a" + song.filename)); + } + + timer++; + + Collection curNotes = song.notes.get(timer); + + if (curNotes.isEmpty()) return; + + for (Entry e : blockPitches.entrySet()) { + for (Note i : curNotes) { + if (isNoteblock(e.getKey()) && (i.pitch == getNote(e.getKey())) && (i.instrument == getInstrumentUnderneath(e.getKey()).ordinal())) + playBlock(e.getKey()); + } + } + } + +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java new file mode 100644 index 0000000..1b3dda5 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java @@ -0,0 +1,68 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.block.enums.Instrument; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; +import xyz.nat1an.notebot.types.Song; +import xyz.nat1an.notebot.utils.NotebotFileManager; +import xyz.nat1an.notebot.utils.NotebotUtils; + +import java.util.Map; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotInfoCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("info") + .then(ClientCommandManager.argument("song", StringArgumentType.greedyString()).suggests(new SongSuggestionProvider()) + .executes(NotebotInfoCommand::run) + ) + ) + ); + } + + public static String listRequirements(Song song) { + StringBuilder result = new StringBuilder(); + + result.append("§6Song: §e").append(song.name); + + for (Map.Entry e : NotebotUtils.INSTRUMENT_TO_ITEM.entrySet()) { + int count = (int) song.requirements.stream().filter(n -> n.instrument == e.getKey().ordinal()).count(); + + if (count != 0) { + result.append("\n§6- §e").append(e.getValue().getName().getString()).append(": §a").append(count); + } + } + + return result.toString(); + } + + private static int run(CommandContext context) { + Song song = NotebotUtils.parse( + NotebotFileManager.getDir().resolve( + "songs/" + context.getArgument("song", String.class) + ) + ); + + mc.player.sendMessage(Text.literal(listRequirements(song))); + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java new file mode 100644 index 0000000..13015c6 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java @@ -0,0 +1,38 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.NotebotPlayer; +import xyz.nat1an.notebot.utils.NotebotFileManager; +import xyz.nat1an.notebot.utils.NotebotUtils; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotStartCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("start") + .executes(NotebotStartCommand::run) + ) + ); + } + + private static int run(CommandContext context) { + NotebotPlayer.playing = true; + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java new file mode 100644 index 0000000..91316eb --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java @@ -0,0 +1,35 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import xyz.nat1an.notebot.NotebotPlayer; + +public class NotebotStopCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("stop") + .executes(NotebotStopCommand::run) + ) + ); + } + + private static int run(CommandContext context) { + NotebotPlayer.playing = false; + + NotebotPlayer.song = null; + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java new file mode 100644 index 0000000..7ae2062 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java @@ -0,0 +1,47 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands.queue; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.NotebotPlayer; +import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotQueueAddCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("queue") + .then(ClientCommandManager.literal("add") + .then(ClientCommandManager.argument("song", StringArgumentType.greedyString()) + .suggests(new SongSuggestionProvider()) + .executes(NotebotQueueAddCommand::run) + ) + ) + ) + ); + } + + private static int run(CommandContext context) { + NotebotPlayer.queue.add(context.getArgument("song", String.class)); + + mc.player.sendMessage( + Text.literal("§6Added §a" + context.getArgument("song", String.class) + "§6 to the queue.") + ); + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java new file mode 100644 index 0000000..43e312b --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java @@ -0,0 +1,44 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands.queue; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.NotebotPlayer; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotQueueCleanCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("queue") + .then(ClientCommandManager.literal("clean") + .executes(NotebotQueueCleanCommand::run) + ) + ) + ); + } + + private static int run(CommandContext context) { + Integer amount = NotebotPlayer.queue.size(); + + NotebotPlayer.queue.clear(); + + mc.player.sendMessage( + Text.literal("§6Cleared §a" + amount + "§6 songs from the queue.") + ); + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java new file mode 100644 index 0000000..013a21a --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java @@ -0,0 +1,49 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands.queue; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.NotebotPlayer; +import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotQueueCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("queue") + .executes(NotebotQueueCommand::run)) + ); + } + + private static String listQueue() { + StringBuilder result = new StringBuilder(); + + result.append("§6Queue:"); + + for (int i = 0; i < NotebotPlayer.queue.size(); i++) { + result.append("\n§6- §e" + i + ": §a" + NotebotPlayer.queue.get(i)); + } + + return result.toString(); + } + + private static int run(CommandContext context) { + mc.player.sendMessage(Text.literal(listQueue())); + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java new file mode 100644 index 0000000..1cc4735 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java @@ -0,0 +1,56 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.commands.queue; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.context.CommandContext; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.text.Text; +import xyz.nat1an.notebot.NotebotPlayer; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotQueueRemoveCommand { + public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, + CommandRegistryAccess commandRegistryAccess) { + clientCommandSourceCommandDispatcher.register( + ClientCommandManager.literal("notebot") + .then(ClientCommandManager.literal("queue") + .then(ClientCommandManager.literal("remove") + .then( + ClientCommandManager.argument( + "index", + IntegerArgumentType.integer() + ) + .executes(NotebotQueueRemoveCommand::run) + ) + ) + ) + ); + } + + private static int run(CommandContext context) { + int index = context.getArgument("index", Integer.class); + + String name; + + try { + name = NotebotPlayer.queue.remove(index); + } catch (IndexOutOfBoundsException e) { + mc.player.sendMessage(Text.literal("§cIndex out of bounds.")); + return 0; + } + + mc.player.sendMessage(Text.literal("§6Removed §a" + name + "§6 at §e" + index + " §6from the queue.")); + + return 1; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java b/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java new file mode 100644 index 0000000..9c7d3ca --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java @@ -0,0 +1,33 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.suggestions; + +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import xyz.nat1an.notebot.NotebotPlayer; + +import java.util.concurrent.CompletableFuture; + +public class QueueSuggestionProvider implements SuggestionProvider { + @Override + public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + String keyword = builder.getInput().substring(builder.getStart()); + + for (String i : NotebotPlayer.queue) { + if (i.toLowerCase().contains(keyword.toLowerCase())) { + builder.suggest(i); + } + } + + return builder.buildFuture(); + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java b/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java new file mode 100644 index 0000000..841df68 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java @@ -0,0 +1,59 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.suggestions; + +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import xyz.nat1an.notebot.utils.NotebotFileManager; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.CompletableFuture; + + +// TODO: Song caching to make it faster +public class SongSuggestionProvider implements SuggestionProvider { + + @Override + public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + // TODO: Song search + String keyword = builder.getInput().substring(builder.getStart()); + + for (String f : getSongs(keyword)) { + builder.suggest(f); + } + + return builder.buildFuture(); + } + + private Set getSongs(String keyword) { + Set files = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + + files.clear(); + + NotebotFileManager.getDir().resolve("songs/").toFile().mkdirs(); + + if (keyword.isEmpty()) { + files.addAll(Arrays.asList(NotebotFileManager.getDir().resolve("songs/").toFile().list())); + return files; + } + + for (String f : NotebotFileManager.getDir().resolve("songs/").toFile().list()) { + if (f.contains(keyword)) { + files.add(f); + } + } + + return files; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/types/Note.java b/remappedSrc/xyz/nat1an/notebot/types/Note.java new file mode 100644 index 0000000..b311625 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/types/Note.java @@ -0,0 +1,33 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + + +package xyz.nat1an.notebot.types; + +public class Note { + + public int pitch; + public int instrument; + + public Note(int pitch, int instrument) { + this.pitch = pitch; + this.instrument = instrument; + } + + @Override + public int hashCode() { + return pitch * 31 + instrument; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Note)) return false; + + Note other = (Note) obj; + return instrument == other.instrument && pitch == other.pitch; + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/types/Song.java b/remappedSrc/xyz/nat1an/notebot/types/Song.java new file mode 100644 index 0000000..b63f9fd --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/types/Song.java @@ -0,0 +1,37 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.types; + +import com.google.common.collect.Multimap; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; + +public class Song { + + public String filename; + public String name; + public String author; + public String format; + + public Multimap notes; + public Set requirements = new HashSet<>(); + public int length; + + public Song(String filename, String name, String author, String format, Multimap notes) { + this.filename = filename; + this.name = name; + this.author = author; + this.format = format; + this.notes = notes; + + notes.values().stream().distinct().forEach(requirements::add); + length = notes.keySet().stream().max(Comparator.naturalOrder()).orElse(0); + } +} diff --git a/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java b/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java new file mode 100644 index 0000000..9b76d29 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java @@ -0,0 +1,52 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.utils; + +import net.minecraft.client.MinecraftClient; +import org.slf4j.Logger; +import xyz.nat1an.notebot.Notebot; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class NotebotFileManager { + + private static Path dir; + private static Logger logger = Notebot.LOGGER; + + public static void init() { + dir = Paths.get(MinecraftClient.getInstance().runDirectory.getPath(), "notebot/"); + if (!dir.toFile().exists()) { + dir.toFile().mkdirs(); + } + } + + public static Path getDir() { + return dir; + } + + public static void createFile(String path) { + try { + if (!fileExists(path)) { + getDir().resolve(path).getParent().toFile().mkdirs(); + Files.createFile(getDir().resolve(path)); + } + } catch (Exception e) { + logger.error("Error Creating File: " + path, e); + } + } + + public static boolean fileExists(String path) { + try { + return getDir().resolve(path).toFile().exists(); + } catch (Exception e) { + return false; + } + } +} \ No newline at end of file diff --git a/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java b/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java new file mode 100644 index 0000000..77404a4 --- /dev/null +++ b/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java @@ -0,0 +1,289 @@ +/* +This file is part of Notebot. +Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with Notebot. If not, see . +*/ + +package xyz.nat1an.notebot.utils; + +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import net.minecraft.block.enums.Instrument; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.text.Text; +import net.minecraft.util.Util; +import org.apache.commons.io.FilenameUtils; +import org.slf4j.Logger; +import xyz.nat1an.notebot.Notebot; +import xyz.nat1an.notebot.types.Note; +import xyz.nat1an.notebot.types.Song; + +import javax.sound.midi.*; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.EnumMap; +import java.util.Locale; + +import static xyz.nat1an.notebot.Notebot.mc; + +public class NotebotUtils { + public static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + public static final EnumMap INSTRUMENT_TO_ITEM = Util.make(new EnumMap<>(javax.sound.midi.Instrument.class), it -> { + it.put(Instrument.HARP, new ItemStack(Items.DIRT)); + it.put(Instrument.BASEDRUM, new ItemStack(Items.STONE)); + it.put(Instrument.SNARE, new ItemStack(Items.SAND)); + it.put(Instrument.HAT, new ItemStack(Items.GLASS)); + it.put(Instrument.BASS, new ItemStack(Items.OAK_WOOD)); + it.put(Instrument.FLUTE, new ItemStack(Items.CLAY)); + it.put(Instrument.BELL, new ItemStack(Items.GOLD_BLOCK)); + it.put(Instrument.GUITAR, new ItemStack(Items.WHITE_WOOL)); + it.put(Instrument.CHIME, new ItemStack(Items.PACKED_ICE)); + it.put(Instrument.XYLOPHONE, new ItemStack(Items.BONE_BLOCK)); + it.put(Instrument.IRON_XYLOPHONE, new ItemStack(Items.IRON_BLOCK)); + it.put(Instrument.COW_BELL, new ItemStack(Items.SOUL_SAND)); + it.put(Instrument.DIDGERIDOO, new ItemStack(Items.PUMPKIN)); + it.put(Instrument.BIT, new ItemStack(Items.EMERALD_BLOCK)); + it.put(Instrument.BANJO, new ItemStack(Items.HAY_BLOCK)); + it.put(Instrument.PLING, new ItemStack(Items.GLOWSTONE)); + }); + private static final int[] NOTE_POSES = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; + private static Logger logger = Notebot.LOGGER; + + public static Song parse(Path path) { + String string = path.toString(); + if (string.endsWith(".mid") || string.endsWith(".midi")) { + return parseMidi(path); + } else if (string.endsWith(".nbs")) { + return parseNbs(path); + } else { + return parseNl(path); + } + } + + public static Song parseNl(Path path) { + Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); + String name = FilenameUtils.getBaseName(path.toString()); + String author = "Unknown"; + + try { + for (String s : Files.readAllLines(path)) { + if (s.startsWith("// Name: ")) { + name = name.substring(9); + } else if (s.startsWith("// Author: ")) { + author = name.substring(11); + } else if (!s.isEmpty()) { + try { + String[] split = s.split(":"); + notes.put(Integer.parseInt(split[0]), new Note(Integer.parseInt(split[1]), Integer.parseInt(split[2]))); + } catch (NumberFormatException | IndexOutOfBoundsException e) { + logger.warn("Error trying to parse note: \u00a7o" + s); + } + } + } + } catch (IOException e) { + logger.error("Error reading NL file!"); + e.printStackTrace(); + } + + return new Song(path.getFileName().toString(), name, author, "Notelist", notes); + } + + public static Song parseMidi(Path path) { + Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); + String name = FilenameUtils.getBaseName(path.toString()); + String author = "Unknown"; + + try { + MidiFileFormat midiFormat = MidiSystem.getMidiFileFormat(path.toFile()); + logger.info(midiFormat.properties().toString()); + + Sequence seq = MidiSystem.getSequence(path.toFile()); + + int res = seq.getResolution(); + int trackCount = 0; + for (Track track : seq.getTracks()) { + // Track track = seq.getTracks()[0] + + long time = 0; + long bpm = 120; + boolean skipNote = false; + int instrument = 0; + for (int i = 0; i < track.size(); i++) { + MidiEvent event = track.get(i); + MidiMessage message = event.getMessage(); + + int ticksPerSecond = (int) (res * (bpm / 60.0)); + time = (long) ((1000d / ticksPerSecond) * event.getTick()); + + long millis = time % 1000; + long second = (time / 1000) % 60; + long minute = (time / (1000 * 60)) % 60; + + String out = trackCount + "-" + event.getTick() + " | [" + String.format(Locale.ENGLISH, "%02d:%02d.%d", minute, second, millis) + "]"; + + if (message instanceof ShortMessage) { + ShortMessage msg = (ShortMessage) message; + + if (msg.getCommand() == 0x90 || msg.getCommand() == 0x80) { + int key = msg.getData1(); + int octave = (key / 12) - 1; + int note = key % 12; + String noteName = NOTE_NAMES[note]; + int velocity = msg.getData2(); + out += " Note " + (msg.getCommand() == 0x80 ? "off" : "on") + " > " + + noteName + octave + " key=" + key + " velocity: " + velocity; + + if (!skipNote) { + notes.put((int) Math.round(time / 50d), new Note(NOTE_POSES[note], instrument)); + skipNote = true; + } else { + skipNote = false; + } + } else if (msg.getCommand() == 0xB0) { + int control = (msg.getLength() > 1) ? (msg.getMessage()[1] & 0xFF) : -1; + int value = (msg.getLength() > 2) ? (msg.getMessage()[2] & 0xFF) : -1; + out += " Control: " + control + " | " + value; + } else if (msg.getCommand() == 0xB0) { + out += " Program: " + msg.getData1(); + // if (msg.getData1() <= 20) instrument = 0; + // else if (msg.getData1() <= 51) instrument = 7; + } else { + out += " Command: " + msg.getCommand() + " > " + msg.getData1() + " | " + msg.getData2(); + } + } else if (message instanceof MetaMessage) { + MetaMessage msg = (MetaMessage) message; + + byte[] data = msg.getData(); + if (msg.getType() == 0x03) { + out += " Meta Instrument: " + new String(data); + } else if (msg.getType() == 0x51) { + int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff); + bpm = 60_000_000 / tempo; + out += " Meta Tempo: " + bpm; + } else { + out += " Meta 0x" + Integer.toHexString(msg.getType()) + ": (" + msg.getClass().getSimpleName() + ")"; + for (byte b : data) + out += (b & 0xff) + " | "; + } + + } else { + out += " Other message: " + message.getClass(); + } + + if (time < 10000) + logger.info(out); + } + + trackCount++; + } + + } catch (Exception e) { + e.printStackTrace(); + } + + return new Song(path.getFileName().toString(), name, author, "MIDI", notes); + } + + public static Song parseNbs(Path path) { + Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); + String name = FilenameUtils.getBaseName(path.toString()); + String author = "Unknown"; + int version = 0; + + try (InputStream input = Files.newInputStream(path)) { + // Signature + version = readShort(input) != 0 ? 0 : input.read(); + + // Skipping most of the headers because we don't need them + input.skip(version >= 3 ? 5 : version >= 1 ? 3 : 2); + String iname = readString(input); + String iauthor = readString(input); + String ioauthor = readString(input); + if (!iname.isEmpty()) + name = iname; + + if (!ioauthor.isEmpty()) { + author = ioauthor; + } else if (!iauthor.isEmpty()) { + author = iauthor; + } + + readString(input); + + float tempo = readShort(input) / 100f; + + input.skip(23); + readString(input); + if (version >= 4) + input.skip(4); + + // Notes + double tick = -1; + short jump; + while ((jump = readShort(input)) != 0) { + tick += jump * (20f / tempo); + + // Iterate through layers + while (readShort(input) != 0) { + int instrument = input.read(); + if (instrument == 0) { + instrument = 0; + } else if (instrument == 1) { + instrument = 4; + } else if (instrument == 2) { + instrument = 1; + } else if (instrument == 3) { + instrument = 2; + } else if (instrument == 4) { + instrument = 3; + } else if (instrument == 5) { + instrument = 7; + } else if (instrument == 6) { + instrument = 5; + } else if (instrument == 7) { + instrument = 6; + } else if (instrument > 15) { + instrument = 0; + } + + int key = input.read() - 33; + if (key < 0) { + mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is below the 2-octave range!")); + key = Math.floorMod(key, 12); + } else if (key > 25) { + mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is above the 2-octave range!")); + key = Math.floorMod(key, 12) + 12; + } + + notes.put((int) Math.round(tick), new Note(key, instrument)); + + if (version >= 4) + input.skip(4); + } + } + } catch (IOException e) { + logger.error("Error reading Nbs file!"); + e.printStackTrace(); + } + + return new Song(path.getFileName().toString(), name, author, "NBS v" + version, notes); + } + + // Reads a little endian short + private static short readShort(InputStream input) throws IOException { + return (short) (input.read() & 0xFF | input.read() << 8); + } + + // Reads a little endian int + private static int readInt(InputStream input) throws IOException { + return input.read() | input.read() << 8 | input.read() << 16 | input.read() << 24; + } + + private static String readString(InputStream input) throws IOException { + return new String(input.readNBytes(readInt(input))); + } +} diff --git a/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java b/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java index 0584796..48b98ff 100644 --- a/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java +++ b/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java @@ -9,7 +9,7 @@ import net.minecraft.block.Block; import net.minecraft.block.NoteBlock; -import net.minecraft.block.enums.Instrument; +import net.minecraft.block.enums.NoteBlockInstrument; import net.minecraft.client.MinecraftClient; import net.minecraft.registry.Registries; import net.minecraft.sound.BlockSoundGroup; @@ -65,8 +65,8 @@ public static Instrument getInstrument(BlockPos pos) { return mc.world.getBlockState(pos).get(NoteBlock.INSTRUMENT); } */ - public static Instrument getInstrumentUnderneath(BlockPos pos) { - if (!isNoteblock(pos)) return Instrument.HARP; + public static NoteBlockInstrument getInstrumentUnderneath(BlockPos pos) { + if (!isNoteblock(pos)) return NoteBlockInstrument.HARP; // Retrieve the block underneath BlockPos posUnderneath = pos.down(); @@ -76,44 +76,44 @@ public static Instrument getInstrumentUnderneath(BlockPos pos) { return blockToInstrument(blockUnderneath); } - public static Instrument blockToInstrument(Block block) { + public static NoteBlockInstrument blockToInstrument(Block block) { // Specific block checks Identifier blockId = Registries.BLOCK.getId(block); String blockIdString = blockId.toString(); - Instrument instrument = Instrument.HARP; // Default to Harp for any other block + NoteBlockInstrument instrument = NoteBlockInstrument.HARP; // Default to Harp for any other block if (blockIdString.equals("minecraft:dirt" ) || blockIdString.equals("minecraft:air")) { - return Instrument.HARP; + return NoteBlockInstrument.HARP; } else if (blockIdString.equals("minecraft:clay")) { - return Instrument.FLUTE; + return NoteBlockInstrument.FLUTE; } else if (blockIdString.equals("minecraft:gold_block")) { - return Instrument.BELL; + return NoteBlockInstrument.BELL; } else if (blockIdString.equals("minecraft:packed_ice")) { - return Instrument.CHIME; + return NoteBlockInstrument.CHIME; } else if (blockIdString.equals("minecraft:bone_block")) { - return Instrument.XYLOPHONE; + return NoteBlockInstrument.XYLOPHONE; } else if (blockIdString.equals("minecraft:iron_block")) { - return Instrument.IRON_XYLOPHONE; + return NoteBlockInstrument.IRON_XYLOPHONE; } else if (blockIdString.equals("minecraft:soul_sand")) { - return Instrument.COW_BELL; + return NoteBlockInstrument.COW_BELL; } else if (blockIdString.equals("minecraft:pumpkin")) { - return Instrument.DIDGERIDOO; + return NoteBlockInstrument.DIDGERIDOO; } else if (blockIdString.equals("minecraft:emerald_block")) { - return Instrument.BIT; + return NoteBlockInstrument.BIT; } else if (blockIdString.equals("minecraft:hay_block")) { - return Instrument.BANJO; + return NoteBlockInstrument.BANJO; } else if (blockIdString.equals("minecraft:glowstone")) { - return Instrument.PLING; + return NoteBlockInstrument.PLING; } else if (blockIdString.equals("minecraft:sand") || blockIdString.equals("minecraft:gravel") || blockIdString.equals("minecraft:concrete_powder")) { - return Instrument.SNARE; + return NoteBlockInstrument.SNARE; } else if (Arrays.asList("minecraft:stone", "minecraft:cobblestone", "minecraft:blackstone", "minecraft:netherrack", "minecraft:nylium", "minecraft:obsidian", "minecraft:quartz", "minecraft:sandstone", "minecraft:ores", "minecraft:bricks", "minecraft:corals", "minecraft:respawn_anchor", "minecraft:bedrock", "minecraft:concrete").contains(blockIdString)) { - return Instrument.BASEDRUM; + return NoteBlockInstrument.BASEDRUM; } else if (blockIdString.equals("minecraft:glass")) { - return Instrument.HAT; + return NoteBlockInstrument.HAT; } @@ -121,16 +121,16 @@ public static Instrument blockToInstrument(Block block) { // Check for blocks with specific materials if (material.equals(BlockSoundGroup.WOOD)) { - return Instrument.BASS; + return NoteBlockInstrument.BASS; } if (material.equals(BlockSoundGroup.WOOL)) { - return Instrument.GUITAR; + return NoteBlockInstrument.GUITAR; } if (material.equals(BlockSoundGroup.GLASS)) { - return Instrument.HAT; + return NoteBlockInstrument.HAT; } if (material.equals(BlockSoundGroup.STONE)) { - return Instrument.BASEDRUM; + return NoteBlockInstrument.BASEDRUM; } @@ -156,11 +156,11 @@ public static boolean loadSong() { try { if (!mc.interactionManager.getCurrentGameMode().isSurvivalLike()) { - mc.player.sendMessage(Text.literal("§cNot in Survival mode!")); + mc.player.sendMessage(Text.literal("§cNot in Survival mode!"), false); return false; } else if (song == null) { - mc.player.sendMessage(Text.literal("§6No song in queue!, Use §c/notebot queue add §6to add a song.")); + mc.player.sendMessage(Text.literal("§6No song in queue!, Use §c/notebot queue add §6to add a song."), false); return false; } @@ -178,16 +178,16 @@ public static boolean loadSong() { NotebotPlayer::isNoteblock).map(BlockPos::toImmutable ).toList(); - HashMap requiredInstruments = new HashMap<>(); - HashMap foundInstruments = new HashMap<>(); + HashMap requiredInstruments = new HashMap<>(); + HashMap foundInstruments = new HashMap<>(); for (Note note : song.requirements) { - Instrument instrument = Instrument.values()[note.instrument]; + NoteBlockInstrument instrument = NoteBlockInstrument.values()[note.instrument]; requiredInstruments.put(instrument, requiredInstruments.getOrDefault(instrument, 0) + 1); for (BlockPos pos : noteblocks) { if (blockPitches.containsKey(pos)) continue; - Instrument blockInstrument = getInstrumentUnderneath(pos); + NoteBlockInstrument blockInstrument = getInstrumentUnderneath(pos); if (note.instrument == blockInstrument.ordinal() && blockPitches.entrySet().stream().filter(e -> e.getValue() == note.pitch).noneMatch(e -> getInstrumentUnderneath(e.getKey()).ordinal() == blockInstrument.ordinal())) { blockPitches.put(pos, note.pitch); foundInstruments.put(blockInstrument, foundInstruments.getOrDefault(blockInstrument, 0) + 1); @@ -196,13 +196,13 @@ public static boolean loadSong() { } } - for (Instrument instrument : requiredInstruments.keySet()) { + for (NoteBlockInstrument instrument : requiredInstruments.keySet()) { int requiredCount = requiredInstruments.get(instrument); int foundCount = foundInstruments.getOrDefault(instrument, 0); int missingCount = requiredCount - foundCount; if (missingCount > 0) { - mc.player.sendMessage(Text.literal("§6Warning: Missing §c" + missingCount + " §6" + instrument + " Noteblocks")); + mc.player.sendMessage(Text.literal("§6Warning: Missing §c" + missingCount + " §6" + instrument + " Noteblocks"), false); } } @@ -214,7 +214,7 @@ public static void onTick(MinecraftClient client) { if (song == null) { if (queue.isEmpty()) { - mc.player.sendMessage(Text.literal("§cYou have no songs in your queue!")); + mc.player.sendMessage(Text.literal("§cYou have no songs in your queue!"), false); stop(); return; } @@ -260,14 +260,14 @@ public static void onTick(MinecraftClient client) { song = null; return; } else { - mc.player.sendMessage(Text.literal("§6The queue is empty, stopping...")); + mc.player.sendMessage(Text.literal("§6The queue is empty, stopping..."), false); stop(); return; } } if (timer == -10) { - mc.player.sendMessage(Text.literal("§6Now Playing: §a" + song.filename)); + mc.player.sendMessage(Text.literal("§6Now Playing: §a" + song.filename), false); } timer++; diff --git a/src/main/java/xyz/nat1an/notebot/commands/NotebotInfoCommand.java b/src/main/java/xyz/nat1an/notebot/commands/NotebotInfoCommand.java index 1b3dda5..4b54b8e 100644 --- a/src/main/java/xyz/nat1an/notebot/commands/NotebotInfoCommand.java +++ b/src/main/java/xyz/nat1an/notebot/commands/NotebotInfoCommand.java @@ -12,7 +12,7 @@ import com.mojang.brigadier.context.CommandContext; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.block.enums.Instrument; +import net.minecraft.block.enums.NoteBlockInstrument; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -43,7 +43,7 @@ public static String listRequirements(Song song) { result.append("§6Song: §e").append(song.name); - for (Map.Entry e : NotebotUtils.INSTRUMENT_TO_ITEM.entrySet()) { + for (Map.Entry e : NotebotUtils.INSTRUMENT_TO_ITEM.entrySet()) { int count = (int) song.requirements.stream().filter(n -> n.instrument == e.getKey().ordinal()).count(); if (count != 0) { @@ -61,7 +61,7 @@ private static int run(CommandContext context) { ) ); - mc.player.sendMessage(Text.literal(listRequirements(song))); + mc.player.sendMessage(Text.literal(listRequirements(song)), false); return 1; } diff --git a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java index 7ae2062..7034684 100644 --- a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java +++ b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java @@ -39,7 +39,8 @@ private static int run(CommandContext context) { NotebotPlayer.queue.add(context.getArgument("song", String.class)); mc.player.sendMessage( - Text.literal("§6Added §a" + context.getArgument("song", String.class) + "§6 to the queue.") + Text.literal("§6Added §a" + context.getArgument("song", String.class) + "§6 to the queue."), + false ); return 1; diff --git a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java index 43e312b..908c6a8 100644 --- a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java +++ b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java @@ -36,7 +36,8 @@ private static int run(CommandContext context) { NotebotPlayer.queue.clear(); mc.player.sendMessage( - Text.literal("§6Cleared §a" + amount + "§6 songs from the queue.") + Text.literal("§6Cleared §a" + amount + "§6 songs from the queue."), + false ); return 1; diff --git a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java index 013a21a..aee7c2d 100644 --- a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java +++ b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java @@ -42,7 +42,7 @@ private static String listQueue() { } private static int run(CommandContext context) { - mc.player.sendMessage(Text.literal(listQueue())); + mc.player.sendMessage(Text.literal(listQueue()), false); return 1; } diff --git a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java index 1cc4735..b8bd892 100644 --- a/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java +++ b/src/main/java/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java @@ -45,11 +45,11 @@ private static int run(CommandContext context) { try { name = NotebotPlayer.queue.remove(index); } catch (IndexOutOfBoundsException e) { - mc.player.sendMessage(Text.literal("§cIndex out of bounds.")); + mc.player.sendMessage(Text.literal("§cIndex out of bounds."), false); return 0; } - mc.player.sendMessage(Text.literal("§6Removed §a" + name + "§6 at §e" + index + " §6from the queue.")); + mc.player.sendMessage(Text.literal("§6Removed §a" + name + "§6 at §e" + index + " §6from the queue."), false); return 1; } diff --git a/src/main/java/xyz/nat1an/notebot/utils/NotebotUtils.java b/src/main/java/xyz/nat1an/notebot/utils/NotebotUtils.java index 837a12b..db7454c 100644 --- a/src/main/java/xyz/nat1an/notebot/utils/NotebotUtils.java +++ b/src/main/java/xyz/nat1an/notebot/utils/NotebotUtils.java @@ -9,7 +9,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; -import net.minecraft.block.enums.Instrument; +import net.minecraft.block.enums.NoteBlockInstrument; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.text.Text; @@ -32,23 +32,23 @@ public class NotebotUtils { public static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; - public static final EnumMap INSTRUMENT_TO_ITEM = Util.make(new EnumMap<>(Instrument.class), it -> { - it.put(Instrument.HARP, new ItemStack(Items.DIRT)); - it.put(Instrument.BASEDRUM, new ItemStack(Items.STONE)); - it.put(Instrument.SNARE, new ItemStack(Items.SAND)); - it.put(Instrument.HAT, new ItemStack(Items.GLASS)); - it.put(Instrument.BASS, new ItemStack(Items.OAK_WOOD)); - it.put(Instrument.FLUTE, new ItemStack(Items.CLAY)); - it.put(Instrument.BELL, new ItemStack(Items.GOLD_BLOCK)); - it.put(Instrument.GUITAR, new ItemStack(Items.WHITE_WOOL)); - it.put(Instrument.CHIME, new ItemStack(Items.PACKED_ICE)); - it.put(Instrument.XYLOPHONE, new ItemStack(Items.BONE_BLOCK)); - it.put(Instrument.IRON_XYLOPHONE, new ItemStack(Items.IRON_BLOCK)); - it.put(Instrument.COW_BELL, new ItemStack(Items.SOUL_SAND)); - it.put(Instrument.DIDGERIDOO, new ItemStack(Items.PUMPKIN)); - it.put(Instrument.BIT, new ItemStack(Items.EMERALD_BLOCK)); - it.put(Instrument.BANJO, new ItemStack(Items.HAY_BLOCK)); - it.put(Instrument.PLING, new ItemStack(Items.GLOWSTONE)); + public static final EnumMap INSTRUMENT_TO_ITEM = Util.make(new EnumMap<>(NoteBlockInstrument.class), it -> { + it.put(NoteBlockInstrument.HARP, new ItemStack(Items.DIRT)); + it.put(NoteBlockInstrument.BASEDRUM, new ItemStack(Items.STONE)); + it.put(NoteBlockInstrument.SNARE, new ItemStack(Items.SAND)); + it.put(NoteBlockInstrument.HAT, new ItemStack(Items.GLASS)); + it.put(NoteBlockInstrument.BASS, new ItemStack(Items.OAK_WOOD)); + it.put(NoteBlockInstrument.FLUTE, new ItemStack(Items.CLAY)); + it.put(NoteBlockInstrument.BELL, new ItemStack(Items.GOLD_BLOCK)); + it.put(NoteBlockInstrument.GUITAR, new ItemStack(Items.WHITE_WOOL)); + it.put(NoteBlockInstrument.CHIME, new ItemStack(Items.PACKED_ICE)); + it.put(NoteBlockInstrument.XYLOPHONE, new ItemStack(Items.BONE_BLOCK)); + it.put(NoteBlockInstrument.IRON_XYLOPHONE, new ItemStack(Items.IRON_BLOCK)); + it.put(NoteBlockInstrument.COW_BELL, new ItemStack(Items.SOUL_SAND)); + it.put(NoteBlockInstrument.DIDGERIDOO, new ItemStack(Items.PUMPKIN)); + it.put(NoteBlockInstrument.BIT, new ItemStack(Items.EMERALD_BLOCK)); + it.put(NoteBlockInstrument.BANJO, new ItemStack(Items.HAY_BLOCK)); + it.put(NoteBlockInstrument.PLING, new ItemStack(Items.GLOWSTONE)); }); private static final int[] NOTE_POSES = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; private static Logger logger = Notebot.LOGGER; @@ -252,10 +252,10 @@ public static Song parseNbs(Path path) { int key = input.read() - 33; if (key < 0) { - mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is below the 2-octave range!")); + mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is below the 2-octave range!"), false); key = Math.floorMod(key, 12); } else if (key > 25) { - mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is above the 2-octave range!")); + mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is above the 2-octave range!"), false); key = Math.floorMod(key, 12) + 12; } From 57667f510c1658969f1140fe1d858bd1949125a5 Mon Sep 17 00:00:00 2001 From: strictpvp Date: Sun, 9 Feb 2025 22:19:17 +0900 Subject: [PATCH 2/3] fixed crash when disconnected --- src/main/java/xyz/nat1an/notebot/NotebotPlayer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java b/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java index 48b98ff..59ac2bf 100644 --- a/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java +++ b/src/main/java/xyz/nat1an/notebot/NotebotPlayer.java @@ -211,6 +211,10 @@ public static boolean loadSong() { public static void onTick(MinecraftClient client) { if (!playing) return; + if (mc.world == null || mc.player == null) { + playing = false; + return; + } if (song == null) { if (queue.isEmpty()) { From 8140c425d54138ecff4dcb1a96b231455d59d69e Mon Sep 17 00:00:00 2001 From: strictpvp Date: Mon, 10 Feb 2025 01:01:31 +0900 Subject: [PATCH 3/3] Remove remapped src, my mistake --- .../xyz/nat1an/notebot/ModRegistries.java | 40 --- remappedSrc/xyz/nat1an/notebot/Notebot.java | 35 --- .../xyz/nat1an/notebot/NotebotPlayer.java | 287 ----------------- .../notebot/commands/NotebotInfoCommand.java | 68 ----- .../notebot/commands/NotebotStartCommand.java | 38 --- .../notebot/commands/NotebotStopCommand.java | 35 --- .../queue/NotebotQueueAddCommand.java | 47 --- .../queue/NotebotQueueCleanCommand.java | 44 --- .../commands/queue/NotebotQueueCommand.java | 49 --- .../queue/NotebotQueueRemoveCommand.java | 56 ---- .../suggestions/QueueSuggestionProvider.java | 33 -- .../suggestions/SongSuggestionProvider.java | 59 ---- .../xyz/nat1an/notebot/types/Note.java | 33 -- .../xyz/nat1an/notebot/types/Song.java | 37 --- .../notebot/utils/NotebotFileManager.java | 52 ---- .../nat1an/notebot/utils/NotebotUtils.java | 289 ------------------ 16 files changed, 1202 deletions(-) delete mode 100644 remappedSrc/xyz/nat1an/notebot/ModRegistries.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/Notebot.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/types/Note.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/types/Song.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java delete mode 100644 remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java diff --git a/remappedSrc/xyz/nat1an/notebot/ModRegistries.java b/remappedSrc/xyz/nat1an/notebot/ModRegistries.java deleted file mode 100644 index 03b3179..0000000 --- a/remappedSrc/xyz/nat1an/notebot/ModRegistries.java +++ /dev/null @@ -1,40 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot; - -import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import xyz.nat1an.notebot.commands.NotebotInfoCommand; -import xyz.nat1an.notebot.commands.NotebotStartCommand; -import xyz.nat1an.notebot.commands.NotebotStopCommand; -import xyz.nat1an.notebot.commands.queue.NotebotQueueAddCommand; -import xyz.nat1an.notebot.commands.queue.NotebotQueueCleanCommand; -import xyz.nat1an.notebot.commands.queue.NotebotQueueCommand; -import xyz.nat1an.notebot.commands.queue.NotebotQueueRemoveCommand; - -public class ModRegistries { - public static void registerModStuff() { - ModRegistries.registerCommands(); - ModRegistries.registerEvents(); - } - - private static void registerCommands() { - ClientCommandRegistrationCallback.EVENT.register(NotebotInfoCommand::register); - ClientCommandRegistrationCallback.EVENT.register(NotebotStartCommand::register); - ClientCommandRegistrationCallback.EVENT.register(NotebotStopCommand::register); - - ClientCommandRegistrationCallback.EVENT.register(NotebotQueueCleanCommand::register); - ClientCommandRegistrationCallback.EVENT.register(NotebotQueueAddCommand::register); - ClientCommandRegistrationCallback.EVENT.register(NotebotQueueRemoveCommand::register); - ClientCommandRegistrationCallback.EVENT.register(NotebotQueueCommand::register); - } - - private static void registerEvents() { - ClientTickEvents.END_CLIENT_TICK.register(NotebotPlayer::onTick); - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/Notebot.java b/remappedSrc/xyz/nat1an/notebot/Notebot.java deleted file mode 100644 index 01ec093..0000000 --- a/remappedSrc/xyz/nat1an/notebot/Notebot.java +++ /dev/null @@ -1,35 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot; - -import net.fabricmc.api.ModInitializer; -import net.minecraft.client.MinecraftClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import xyz.nat1an.notebot.utils.NotebotFileManager; - -public class Notebot implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final Logger LOGGER = LoggerFactory.getLogger("notebot"); - public static final MinecraftClient mc = MinecraftClient.getInstance(); - - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello Fabric world!"); - - NotebotFileManager.init(); - - ModRegistries.registerModStuff(); - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java b/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java deleted file mode 100644 index 0584796..0000000 --- a/remappedSrc/xyz/nat1an/notebot/NotebotPlayer.java +++ /dev/null @@ -1,287 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot; - -import net.minecraft.block.Block; -import net.minecraft.block.NoteBlock; -import net.minecraft.block.enums.Instrument; -import net.minecraft.client.MinecraftClient; -import net.minecraft.registry.Registries; -import net.minecraft.sound.BlockSoundGroup; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import xyz.nat1an.notebot.types.Note; -import xyz.nat1an.notebot.types.Song; -import xyz.nat1an.notebot.utils.NotebotFileManager; -import xyz.nat1an.notebot.utils.NotebotUtils; - -import java.util.*; -import java.util.Map.Entry; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotPlayer { - /* Status */ - public static boolean playing = false; - - /* Some settings */ - public static boolean loop = false; - - /* The loaded song */ - public static Song song; - public static List trail = new ArrayList<>(); - public static List queue = new ArrayList<>(); - - /* Map of noteblocks and their pitch around the player [blockpos:pitch] */ - private static Map blockPitches = new HashMap<>(); - private static int timer = -10; - private static int tuneDelay = 0; - - public static int getNote(BlockPos pos) { - if (!isNoteblock(pos)) return -1; - - return mc.world.getBlockState(pos).get(NoteBlock.NOTE); - } - - public static void playBlock(BlockPos pos) { - if (!isNoteblock(pos)) return; - - mc.interactionManager.attackBlock(pos, Direction.UP); - mc.player.swingHand(Hand.MAIN_HAND); - } -/* - public static Instrument getInstrument(BlockPos pos) { - if (!isNoteblock(pos)) return Instrument.HARP; - return mc.world.getBlockState(pos).get(NoteBlock.INSTRUMENT); - } -*/ - public static Instrument getInstrumentUnderneath(BlockPos pos) { - if (!isNoteblock(pos)) return Instrument.HARP; - - // Retrieve the block underneath - BlockPos posUnderneath = pos.down(); - Block blockUnderneath = mc.world.getBlockState(posUnderneath).getBlock(); - - // Return the instrument associated with the block underneath - return blockToInstrument(blockUnderneath); - } - - public static Instrument blockToInstrument(Block block) { - - // Specific block checks - Identifier blockId = Registries.BLOCK.getId(block); - String blockIdString = blockId.toString(); - Instrument instrument = Instrument.HARP; // Default to Harp for any other block - - - if (blockIdString.equals("minecraft:dirt" ) || blockIdString.equals("minecraft:air")) { - return Instrument.HARP; - } else if (blockIdString.equals("minecraft:clay")) { - return Instrument.FLUTE; - } else if (blockIdString.equals("minecraft:gold_block")) { - return Instrument.BELL; - } else if (blockIdString.equals("minecraft:packed_ice")) { - return Instrument.CHIME; - } else if (blockIdString.equals("minecraft:bone_block")) { - return Instrument.XYLOPHONE; - } else if (blockIdString.equals("minecraft:iron_block")) { - return Instrument.IRON_XYLOPHONE; - } else if (blockIdString.equals("minecraft:soul_sand")) { - return Instrument.COW_BELL; - } else if (blockIdString.equals("minecraft:pumpkin")) { - return Instrument.DIDGERIDOO; - } else if (blockIdString.equals("minecraft:emerald_block")) { - return Instrument.BIT; - } else if (blockIdString.equals("minecraft:hay_block")) { - return Instrument.BANJO; - } else if (blockIdString.equals("minecraft:glowstone")) { - return Instrument.PLING; - } else if (blockIdString.equals("minecraft:sand") || blockIdString.equals("minecraft:gravel") || blockIdString.equals("minecraft:concrete_powder")) { - return Instrument.SNARE; - } else if (Arrays.asList("minecraft:stone", "minecraft:cobblestone", "minecraft:blackstone", "minecraft:netherrack", "minecraft:nylium", "minecraft:obsidian", - "minecraft:quartz", "minecraft:sandstone", "minecraft:ores", "minecraft:bricks", "minecraft:corals", - "minecraft:respawn_anchor", "minecraft:bedrock", "minecraft:concrete").contains(blockIdString)) { - return Instrument.BASEDRUM; - } else if (blockIdString.equals("minecraft:glass")) { - return Instrument.HAT; - } - - - BlockSoundGroup material = block.getDefaultState().getSoundGroup(); - - // Check for blocks with specific materials - if (material.equals(BlockSoundGroup.WOOD)) { - return Instrument.BASS; - } - if (material.equals(BlockSoundGroup.WOOL)) { - return Instrument.GUITAR; - } - if (material.equals(BlockSoundGroup.GLASS)) { - return Instrument.HAT; - } - if (material.equals(BlockSoundGroup.STONE)) { - return Instrument.BASEDRUM; - } - - - - return instrument; - } - - public static boolean isNoteblock(BlockPos pos) { - // Checks if this block is a noteblock and the noteblock can be played - return mc.world.getBlockState(pos).getBlock() instanceof NoteBlock && mc.world.getBlockState(pos.up()).isAir(); - } - - public static void stop() { - playing = false; - song = null; - blockPitches.clear(); - timer = -10; - tuneDelay = 0; - } - - public static boolean loadSong() { - blockPitches.clear(); - - try { - if (!mc.interactionManager.getCurrentGameMode().isSurvivalLike()) { - mc.player.sendMessage(Text.literal("§cNot in Survival mode!")); - - return false; - } else if (song == null) { - mc.player.sendMessage(Text.literal("§6No song in queue!, Use §c/notebot queue add §6to add a song.")); - - return false; - } - } catch (NullPointerException e) { - return false; - } - - timer = -10; - - BlockPos playerEyePos = new BlockPos((int) mc.player.getEyePos().x, (int) mc.player.getEyePos().y, (int) mc.player.getEyePos().z); - - List noteblocks = BlockPos.streamOutwards( - playerEyePos, 5, 5, 5 - ).filter( - NotebotPlayer::isNoteblock).map(BlockPos::toImmutable - ).toList(); - - HashMap requiredInstruments = new HashMap<>(); - HashMap foundInstruments = new HashMap<>(); - - for (Note note : song.requirements) { - Instrument instrument = Instrument.values()[note.instrument]; - requiredInstruments.put(instrument, requiredInstruments.getOrDefault(instrument, 0) + 1); - for (BlockPos pos : noteblocks) { - if (blockPitches.containsKey(pos)) continue; - - Instrument blockInstrument = getInstrumentUnderneath(pos); - if (note.instrument == blockInstrument.ordinal() && blockPitches.entrySet().stream().filter(e -> e.getValue() == note.pitch).noneMatch(e -> getInstrumentUnderneath(e.getKey()).ordinal() == blockInstrument.ordinal())) { - blockPitches.put(pos, note.pitch); - foundInstruments.put(blockInstrument, foundInstruments.getOrDefault(blockInstrument, 0) + 1); - break; - } - } - } - - for (Instrument instrument : requiredInstruments.keySet()) { - int requiredCount = requiredInstruments.get(instrument); - int foundCount = foundInstruments.getOrDefault(instrument, 0); - int missingCount = requiredCount - foundCount; - - if (missingCount > 0) { - mc.player.sendMessage(Text.literal("§6Warning: Missing §c" + missingCount + " §6" + instrument + " Noteblocks")); - } - } - - return true; - } - - public static void onTick(MinecraftClient client) { - if (!playing) return; - - if (song == null) { - if (queue.isEmpty()) { - mc.player.sendMessage(Text.literal("§cYou have no songs in your queue!")); - stop(); - return; - } - - NotebotPlayer.song = NotebotUtils.parse( - NotebotFileManager.getDir().resolve( - "songs/" + NotebotPlayer.queue.remove(0) - ) - ); - - loadSong(); - } - - // Tune Noteblocks - for (Entry e : blockPitches.entrySet()) { - int note = getNote(e.getKey()); - if (note == -1) - continue; - - if (note != e.getValue()) { - if (tuneDelay < 5) { - tuneDelay++; - return; - } - - int neededNote = e.getValue() < note ? e.getValue() + 25 : e.getValue(); - int reqTunes = Math.min(25, neededNote - note); - for (int i = 0; i < reqTunes; i++) - mc.interactionManager.interactBlock(mc.player, - Hand.MAIN_HAND, new BlockHitResult(Vec3d.ofCenter(e.getKey(), 1), Direction.UP, e.getKey(), true)); - - tuneDelay = 0; - - return; - } - } - - // Loop - if (timer - 10 > song.length) { - if (loop) { - timer = -10; - } else if (!queue.isEmpty()) { - song = null; - return; - } else { - mc.player.sendMessage(Text.literal("§6The queue is empty, stopping...")); - stop(); - return; - } - } - - if (timer == -10) { - mc.player.sendMessage(Text.literal("§6Now Playing: §a" + song.filename)); - } - - timer++; - - Collection curNotes = song.notes.get(timer); - - if (curNotes.isEmpty()) return; - - for (Entry e : blockPitches.entrySet()) { - for (Note i : curNotes) { - if (isNoteblock(e.getKey()) && (i.pitch == getNote(e.getKey())) && (i.instrument == getInstrumentUnderneath(e.getKey()).ordinal())) - playBlock(e.getKey()); - } - } - } - -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java deleted file mode 100644 index 1b3dda5..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/NotebotInfoCommand.java +++ /dev/null @@ -1,68 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.block.enums.Instrument; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; -import xyz.nat1an.notebot.types.Song; -import xyz.nat1an.notebot.utils.NotebotFileManager; -import xyz.nat1an.notebot.utils.NotebotUtils; - -import java.util.Map; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotInfoCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("info") - .then(ClientCommandManager.argument("song", StringArgumentType.greedyString()).suggests(new SongSuggestionProvider()) - .executes(NotebotInfoCommand::run) - ) - ) - ); - } - - public static String listRequirements(Song song) { - StringBuilder result = new StringBuilder(); - - result.append("§6Song: §e").append(song.name); - - for (Map.Entry e : NotebotUtils.INSTRUMENT_TO_ITEM.entrySet()) { - int count = (int) song.requirements.stream().filter(n -> n.instrument == e.getKey().ordinal()).count(); - - if (count != 0) { - result.append("\n§6- §e").append(e.getValue().getName().getString()).append(": §a").append(count); - } - } - - return result.toString(); - } - - private static int run(CommandContext context) { - Song song = NotebotUtils.parse( - NotebotFileManager.getDir().resolve( - "songs/" + context.getArgument("song", String.class) - ) - ); - - mc.player.sendMessage(Text.literal(listRequirements(song))); - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java deleted file mode 100644 index 13015c6..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStartCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.NotebotPlayer; -import xyz.nat1an.notebot.utils.NotebotFileManager; -import xyz.nat1an.notebot.utils.NotebotUtils; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotStartCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("start") - .executes(NotebotStartCommand::run) - ) - ); - } - - private static int run(CommandContext context) { - NotebotPlayer.playing = true; - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java deleted file mode 100644 index 91316eb..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/NotebotStopCommand.java +++ /dev/null @@ -1,35 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import xyz.nat1an.notebot.NotebotPlayer; - -public class NotebotStopCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("stop") - .executes(NotebotStopCommand::run) - ) - ); - } - - private static int run(CommandContext context) { - NotebotPlayer.playing = false; - - NotebotPlayer.song = null; - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java deleted file mode 100644 index 7ae2062..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueAddCommand.java +++ /dev/null @@ -1,47 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands.queue; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.NotebotPlayer; -import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotQueueAddCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("queue") - .then(ClientCommandManager.literal("add") - .then(ClientCommandManager.argument("song", StringArgumentType.greedyString()) - .suggests(new SongSuggestionProvider()) - .executes(NotebotQueueAddCommand::run) - ) - ) - ) - ); - } - - private static int run(CommandContext context) { - NotebotPlayer.queue.add(context.getArgument("song", String.class)); - - mc.player.sendMessage( - Text.literal("§6Added §a" + context.getArgument("song", String.class) + "§6 to the queue.") - ); - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java deleted file mode 100644 index 43e312b..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCleanCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands.queue; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.NotebotPlayer; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotQueueCleanCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("queue") - .then(ClientCommandManager.literal("clean") - .executes(NotebotQueueCleanCommand::run) - ) - ) - ); - } - - private static int run(CommandContext context) { - Integer amount = NotebotPlayer.queue.size(); - - NotebotPlayer.queue.clear(); - - mc.player.sendMessage( - Text.literal("§6Cleared §a" + amount + "§6 songs from the queue.") - ); - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java deleted file mode 100644 index 013a21a..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands.queue; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.NotebotPlayer; -import xyz.nat1an.notebot.suggestions.SongSuggestionProvider; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotQueueCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("queue") - .executes(NotebotQueueCommand::run)) - ); - } - - private static String listQueue() { - StringBuilder result = new StringBuilder(); - - result.append("§6Queue:"); - - for (int i = 0; i < NotebotPlayer.queue.size(); i++) { - result.append("\n§6- §e" + i + ": §a" + NotebotPlayer.queue.get(i)); - } - - return result.toString(); - } - - private static int run(CommandContext context) { - mc.player.sendMessage(Text.literal(listQueue())); - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java b/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java deleted file mode 100644 index 1cc4735..0000000 --- a/remappedSrc/xyz/nat1an/notebot/commands/queue/NotebotQueueRemoveCommand.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.commands.queue; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.text.Text; -import xyz.nat1an.notebot.NotebotPlayer; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotQueueRemoveCommand { - public static void register(CommandDispatcher clientCommandSourceCommandDispatcher, - CommandRegistryAccess commandRegistryAccess) { - clientCommandSourceCommandDispatcher.register( - ClientCommandManager.literal("notebot") - .then(ClientCommandManager.literal("queue") - .then(ClientCommandManager.literal("remove") - .then( - ClientCommandManager.argument( - "index", - IntegerArgumentType.integer() - ) - .executes(NotebotQueueRemoveCommand::run) - ) - ) - ) - ); - } - - private static int run(CommandContext context) { - int index = context.getArgument("index", Integer.class); - - String name; - - try { - name = NotebotPlayer.queue.remove(index); - } catch (IndexOutOfBoundsException e) { - mc.player.sendMessage(Text.literal("§cIndex out of bounds.")); - return 0; - } - - mc.player.sendMessage(Text.literal("§6Removed §a" + name + "§6 at §e" + index + " §6from the queue.")); - - return 1; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java b/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java deleted file mode 100644 index 9c7d3ca..0000000 --- a/remappedSrc/xyz/nat1an/notebot/suggestions/QueueSuggestionProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.suggestions; - -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.SuggestionProvider; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import xyz.nat1an.notebot.NotebotPlayer; - -import java.util.concurrent.CompletableFuture; - -public class QueueSuggestionProvider implements SuggestionProvider { - @Override - public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { - String keyword = builder.getInput().substring(builder.getStart()); - - for (String i : NotebotPlayer.queue) { - if (i.toLowerCase().contains(keyword.toLowerCase())) { - builder.suggest(i); - } - } - - return builder.buildFuture(); - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java b/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java deleted file mode 100644 index 841df68..0000000 --- a/remappedSrc/xyz/nat1an/notebot/suggestions/SongSuggestionProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.suggestions; - -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.SuggestionProvider; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import xyz.nat1an.notebot.utils.NotebotFileManager; - -import java.util.Arrays; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.CompletableFuture; - - -// TODO: Song caching to make it faster -public class SongSuggestionProvider implements SuggestionProvider { - - @Override - public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { - // TODO: Song search - String keyword = builder.getInput().substring(builder.getStart()); - - for (String f : getSongs(keyword)) { - builder.suggest(f); - } - - return builder.buildFuture(); - } - - private Set getSongs(String keyword) { - Set files = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - - files.clear(); - - NotebotFileManager.getDir().resolve("songs/").toFile().mkdirs(); - - if (keyword.isEmpty()) { - files.addAll(Arrays.asList(NotebotFileManager.getDir().resolve("songs/").toFile().list())); - return files; - } - - for (String f : NotebotFileManager.getDir().resolve("songs/").toFile().list()) { - if (f.contains(keyword)) { - files.add(f); - } - } - - return files; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/types/Note.java b/remappedSrc/xyz/nat1an/notebot/types/Note.java deleted file mode 100644 index b311625..0000000 --- a/remappedSrc/xyz/nat1an/notebot/types/Note.java +++ /dev/null @@ -1,33 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - - -package xyz.nat1an.notebot.types; - -public class Note { - - public int pitch; - public int instrument; - - public Note(int pitch, int instrument) { - this.pitch = pitch; - this.instrument = instrument; - } - - @Override - public int hashCode() { - return pitch * 31 + instrument; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Note)) return false; - - Note other = (Note) obj; - return instrument == other.instrument && pitch == other.pitch; - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/types/Song.java b/remappedSrc/xyz/nat1an/notebot/types/Song.java deleted file mode 100644 index b63f9fd..0000000 --- a/remappedSrc/xyz/nat1an/notebot/types/Song.java +++ /dev/null @@ -1,37 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.types; - -import com.google.common.collect.Multimap; - -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; - -public class Song { - - public String filename; - public String name; - public String author; - public String format; - - public Multimap notes; - public Set requirements = new HashSet<>(); - public int length; - - public Song(String filename, String name, String author, String format, Multimap notes) { - this.filename = filename; - this.name = name; - this.author = author; - this.format = format; - this.notes = notes; - - notes.values().stream().distinct().forEach(requirements::add); - length = notes.keySet().stream().max(Comparator.naturalOrder()).orElse(0); - } -} diff --git a/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java b/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java deleted file mode 100644 index 9b76d29..0000000 --- a/remappedSrc/xyz/nat1an/notebot/utils/NotebotFileManager.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.utils; - -import net.minecraft.client.MinecraftClient; -import org.slf4j.Logger; -import xyz.nat1an.notebot.Notebot; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class NotebotFileManager { - - private static Path dir; - private static Logger logger = Notebot.LOGGER; - - public static void init() { - dir = Paths.get(MinecraftClient.getInstance().runDirectory.getPath(), "notebot/"); - if (!dir.toFile().exists()) { - dir.toFile().mkdirs(); - } - } - - public static Path getDir() { - return dir; - } - - public static void createFile(String path) { - try { - if (!fileExists(path)) { - getDir().resolve(path).getParent().toFile().mkdirs(); - Files.createFile(getDir().resolve(path)); - } - } catch (Exception e) { - logger.error("Error Creating File: " + path, e); - } - } - - public static boolean fileExists(String path) { - try { - return getDir().resolve(path).toFile().exists(); - } catch (Exception e) { - return false; - } - } -} \ No newline at end of file diff --git a/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java b/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java deleted file mode 100644 index 77404a4..0000000 --- a/remappedSrc/xyz/nat1an/notebot/utils/NotebotUtils.java +++ /dev/null @@ -1,289 +0,0 @@ -/* -This file is part of Notebot. -Notebot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -Notebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with Notebot. If not, see . -*/ - -package xyz.nat1an.notebot.utils; - -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import net.minecraft.block.enums.Instrument; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.text.Text; -import net.minecraft.util.Util; -import org.apache.commons.io.FilenameUtils; -import org.slf4j.Logger; -import xyz.nat1an.notebot.Notebot; -import xyz.nat1an.notebot.types.Note; -import xyz.nat1an.notebot.types.Song; - -import javax.sound.midi.*; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.EnumMap; -import java.util.Locale; - -import static xyz.nat1an.notebot.Notebot.mc; - -public class NotebotUtils { - public static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; - public static final EnumMap INSTRUMENT_TO_ITEM = Util.make(new EnumMap<>(javax.sound.midi.Instrument.class), it -> { - it.put(Instrument.HARP, new ItemStack(Items.DIRT)); - it.put(Instrument.BASEDRUM, new ItemStack(Items.STONE)); - it.put(Instrument.SNARE, new ItemStack(Items.SAND)); - it.put(Instrument.HAT, new ItemStack(Items.GLASS)); - it.put(Instrument.BASS, new ItemStack(Items.OAK_WOOD)); - it.put(Instrument.FLUTE, new ItemStack(Items.CLAY)); - it.put(Instrument.BELL, new ItemStack(Items.GOLD_BLOCK)); - it.put(Instrument.GUITAR, new ItemStack(Items.WHITE_WOOL)); - it.put(Instrument.CHIME, new ItemStack(Items.PACKED_ICE)); - it.put(Instrument.XYLOPHONE, new ItemStack(Items.BONE_BLOCK)); - it.put(Instrument.IRON_XYLOPHONE, new ItemStack(Items.IRON_BLOCK)); - it.put(Instrument.COW_BELL, new ItemStack(Items.SOUL_SAND)); - it.put(Instrument.DIDGERIDOO, new ItemStack(Items.PUMPKIN)); - it.put(Instrument.BIT, new ItemStack(Items.EMERALD_BLOCK)); - it.put(Instrument.BANJO, new ItemStack(Items.HAY_BLOCK)); - it.put(Instrument.PLING, new ItemStack(Items.GLOWSTONE)); - }); - private static final int[] NOTE_POSES = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; - private static Logger logger = Notebot.LOGGER; - - public static Song parse(Path path) { - String string = path.toString(); - if (string.endsWith(".mid") || string.endsWith(".midi")) { - return parseMidi(path); - } else if (string.endsWith(".nbs")) { - return parseNbs(path); - } else { - return parseNl(path); - } - } - - public static Song parseNl(Path path) { - Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); - String name = FilenameUtils.getBaseName(path.toString()); - String author = "Unknown"; - - try { - for (String s : Files.readAllLines(path)) { - if (s.startsWith("// Name: ")) { - name = name.substring(9); - } else if (s.startsWith("// Author: ")) { - author = name.substring(11); - } else if (!s.isEmpty()) { - try { - String[] split = s.split(":"); - notes.put(Integer.parseInt(split[0]), new Note(Integer.parseInt(split[1]), Integer.parseInt(split[2]))); - } catch (NumberFormatException | IndexOutOfBoundsException e) { - logger.warn("Error trying to parse note: \u00a7o" + s); - } - } - } - } catch (IOException e) { - logger.error("Error reading NL file!"); - e.printStackTrace(); - } - - return new Song(path.getFileName().toString(), name, author, "Notelist", notes); - } - - public static Song parseMidi(Path path) { - Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); - String name = FilenameUtils.getBaseName(path.toString()); - String author = "Unknown"; - - try { - MidiFileFormat midiFormat = MidiSystem.getMidiFileFormat(path.toFile()); - logger.info(midiFormat.properties().toString()); - - Sequence seq = MidiSystem.getSequence(path.toFile()); - - int res = seq.getResolution(); - int trackCount = 0; - for (Track track : seq.getTracks()) { - // Track track = seq.getTracks()[0] - - long time = 0; - long bpm = 120; - boolean skipNote = false; - int instrument = 0; - for (int i = 0; i < track.size(); i++) { - MidiEvent event = track.get(i); - MidiMessage message = event.getMessage(); - - int ticksPerSecond = (int) (res * (bpm / 60.0)); - time = (long) ((1000d / ticksPerSecond) * event.getTick()); - - long millis = time % 1000; - long second = (time / 1000) % 60; - long minute = (time / (1000 * 60)) % 60; - - String out = trackCount + "-" + event.getTick() + " | [" + String.format(Locale.ENGLISH, "%02d:%02d.%d", minute, second, millis) + "]"; - - if (message instanceof ShortMessage) { - ShortMessage msg = (ShortMessage) message; - - if (msg.getCommand() == 0x90 || msg.getCommand() == 0x80) { - int key = msg.getData1(); - int octave = (key / 12) - 1; - int note = key % 12; - String noteName = NOTE_NAMES[note]; - int velocity = msg.getData2(); - out += " Note " + (msg.getCommand() == 0x80 ? "off" : "on") + " > " - + noteName + octave + " key=" + key + " velocity: " + velocity; - - if (!skipNote) { - notes.put((int) Math.round(time / 50d), new Note(NOTE_POSES[note], instrument)); - skipNote = true; - } else { - skipNote = false; - } - } else if (msg.getCommand() == 0xB0) { - int control = (msg.getLength() > 1) ? (msg.getMessage()[1] & 0xFF) : -1; - int value = (msg.getLength() > 2) ? (msg.getMessage()[2] & 0xFF) : -1; - out += " Control: " + control + " | " + value; - } else if (msg.getCommand() == 0xB0) { - out += " Program: " + msg.getData1(); - // if (msg.getData1() <= 20) instrument = 0; - // else if (msg.getData1() <= 51) instrument = 7; - } else { - out += " Command: " + msg.getCommand() + " > " + msg.getData1() + " | " + msg.getData2(); - } - } else if (message instanceof MetaMessage) { - MetaMessage msg = (MetaMessage) message; - - byte[] data = msg.getData(); - if (msg.getType() == 0x03) { - out += " Meta Instrument: " + new String(data); - } else if (msg.getType() == 0x51) { - int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff); - bpm = 60_000_000 / tempo; - out += " Meta Tempo: " + bpm; - } else { - out += " Meta 0x" + Integer.toHexString(msg.getType()) + ": (" + msg.getClass().getSimpleName() + ")"; - for (byte b : data) - out += (b & 0xff) + " | "; - } - - } else { - out += " Other message: " + message.getClass(); - } - - if (time < 10000) - logger.info(out); - } - - trackCount++; - } - - } catch (Exception e) { - e.printStackTrace(); - } - - return new Song(path.getFileName().toString(), name, author, "MIDI", notes); - } - - public static Song parseNbs(Path path) { - Multimap notes = MultimapBuilder.linkedHashKeys().arrayListValues().build(); - String name = FilenameUtils.getBaseName(path.toString()); - String author = "Unknown"; - int version = 0; - - try (InputStream input = Files.newInputStream(path)) { - // Signature - version = readShort(input) != 0 ? 0 : input.read(); - - // Skipping most of the headers because we don't need them - input.skip(version >= 3 ? 5 : version >= 1 ? 3 : 2); - String iname = readString(input); - String iauthor = readString(input); - String ioauthor = readString(input); - if (!iname.isEmpty()) - name = iname; - - if (!ioauthor.isEmpty()) { - author = ioauthor; - } else if (!iauthor.isEmpty()) { - author = iauthor; - } - - readString(input); - - float tempo = readShort(input) / 100f; - - input.skip(23); - readString(input); - if (version >= 4) - input.skip(4); - - // Notes - double tick = -1; - short jump; - while ((jump = readShort(input)) != 0) { - tick += jump * (20f / tempo); - - // Iterate through layers - while (readShort(input) != 0) { - int instrument = input.read(); - if (instrument == 0) { - instrument = 0; - } else if (instrument == 1) { - instrument = 4; - } else if (instrument == 2) { - instrument = 1; - } else if (instrument == 3) { - instrument = 2; - } else if (instrument == 4) { - instrument = 3; - } else if (instrument == 5) { - instrument = 7; - } else if (instrument == 6) { - instrument = 5; - } else if (instrument == 7) { - instrument = 6; - } else if (instrument > 15) { - instrument = 0; - } - - int key = input.read() - 33; - if (key < 0) { - mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is below the 2-octave range!")); - key = Math.floorMod(key, 12); - } else if (key > 25) { - mc.player.sendMessage(Text.literal("Note @" + tick + " Key: " + key + " is above the 2-octave range!")); - key = Math.floorMod(key, 12) + 12; - } - - notes.put((int) Math.round(tick), new Note(key, instrument)); - - if (version >= 4) - input.skip(4); - } - } - } catch (IOException e) { - logger.error("Error reading Nbs file!"); - e.printStackTrace(); - } - - return new Song(path.getFileName().toString(), name, author, "NBS v" + version, notes); - } - - // Reads a little endian short - private static short readShort(InputStream input) throws IOException { - return (short) (input.read() & 0xFF | input.read() << 8); - } - - // Reads a little endian int - private static int readInt(InputStream input) throws IOException { - return input.read() | input.read() << 8 | input.read() << 16 | input.read() << 24; - } - - private static String readString(InputStream input) throws IOException { - return new String(input.readNBytes(readInt(input))); - } -}