From 26d925f4fab9387ad55d2f6f451b63853954d6a3 Mon Sep 17 00:00:00 2001 From: EnderKill98 Date: Wed, 17 Apr 2024 17:26:15 +0200 Subject: [PATCH] Add option and support to specify "nothing" as a mapped instrument Allows to discard instruments entirely --- .../disc_jockey/DiscjockeyCommand.java | 16 ++++++--- .../semmiedev/disc_jockey/SongPlayer.java | 36 ++++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/main/java/semmiedev/disc_jockey/DiscjockeyCommand.java b/src/main/java/semmiedev/disc_jockey/DiscjockeyCommand.java index e0e863b..33898dc 100644 --- a/src/main/java/semmiedev/disc_jockey/DiscjockeyCommand.java +++ b/src/main/java/semmiedev/disc_jockey/DiscjockeyCommand.java @@ -10,6 +10,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.command.CommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import org.jetbrains.annotations.Nullable; import semmiedev.disc_jockey.gui.screen.DiscJockeyScreen; import java.util.ArrayList; @@ -30,6 +31,8 @@ public class DiscjockeyCommand { } final ArrayList instrumentNamesAndAll = new ArrayList<>(instrumentNames); instrumentNamesAndAll.add("all"); + final ArrayList instrumentNamesAndNothing = new ArrayList<>(instrumentNames); + instrumentNamesAndNothing.add("nothing"); commandDispatcher.register( literal("discjockey") @@ -120,11 +123,11 @@ public class DiscjockeyCommand { .then(argument("originalInstrument", StringArgumentType.word()) .suggests((context, builder) -> CommandSource.suggestMatching(instrumentNamesAndAll, builder)) .then(argument("newInstrument", StringArgumentType.word()) - .suggests((context, builder) -> CommandSource.suggestMatching(instrumentNames, builder)) + .suggests((context, builder) -> CommandSource.suggestMatching(instrumentNamesAndNothing, builder)) .executes(context -> { String originalInstrumentStr = StringArgumentType.getString(context, "originalInstrument"); String newInstrumentStr = StringArgumentType.getString(context, "newInstrument"); - Instrument originalInstrument = null, newInstrument = null; + @Nullable Instrument originalInstrument = null, newInstrument = null; for(Instrument maybeInstrument : Instrument.values()) { if(maybeInstrument.toString().equalsIgnoreCase(originalInstrumentStr)) { originalInstrument = maybeInstrument; @@ -139,11 +142,14 @@ public class DiscjockeyCommand { return 0; } - if(newInstrument == null) { + if(newInstrument == null && !newInstrumentStr.equalsIgnoreCase("nothing")) { context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".invalid_instrument", newInstrumentStr)); return 0; } + // (originalInstrument == null) means: all instruments + // (newInstrument == null) means: nothing (represented by null in hashmap, so no special handling below) + if(originalInstrument == null) { // All instruments for(Instrument instrument : Instrument.values()) { @@ -198,8 +204,8 @@ public class DiscjockeyCommand { } maps .append(entry.getKey().toString().toLowerCase()) - .append(" -> ") - .append(entry.getValue().toString().toLowerCase()); + .append("->") + .append(entry.getValue() == null ? "nothing" : entry.getValue().toString().toLowerCase()); } context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".mapped_instruments", maps.toString())); return 1; diff --git a/src/main/java/semmiedev/disc_jockey/SongPlayer.java b/src/main/java/semmiedev/disc_jockey/SongPlayer.java index 78eb6dd..a7e73c0 100644 --- a/src/main/java/semmiedev/disc_jockey/SongPlayer.java +++ b/src/main/java/semmiedev/disc_jockey/SongPlayer.java @@ -21,6 +21,7 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.*; import net.minecraft.world.GameMode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.HashMap; @@ -66,7 +67,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { Main.TICK_LISTENERS.add(this); } - public @NotNull HashMap instrumentMap = new HashMap<>(); // Toy + public @NotNull HashMap instrumentMap = new HashMap<>(); // Toy public synchronized void startPlaybackThread() { if(Main.config.disableAsyncPlayback) { playbackThread = null; @@ -164,7 +165,12 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { long note = song.notes[index]; final long now = System.currentTimeMillis(); if ((short)note <= Math.round(tick)) { - BlockPos blockPos = noteBlocks.get(Note.INSTRUMENTS[(byte)(note >> Note.INSTRUMENT_SHIFT)]).get((byte)(note >> Note.NOTE_SHIFT)); + @Nullable BlockPos blockPos = noteBlocks.get(Note.INSTRUMENTS[(byte)(note >> Note.INSTRUMENT_SHIFT)]).get((byte)(note >> Note.NOTE_SHIFT)); + if(blockPos == null) { + // Instrument got likely mapped to "nothing". Skip it + index++; + continue; + } if (!canInteractWith(client.player, blockPos)) { stop(); client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED)); @@ -273,6 +279,13 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { if(!instrumentMap.isEmpty()) { HashMap> newNoteblocksForInstrument = new HashMap<>(); for(Instrument orig : noteblocksForInstrument.keySet()) { + Instrument mappedInstrument = instrumentMap.getOrDefault(orig, orig); + if(mappedInstrument == null) { + // Instrument got likely mapped to "nothing" + newNoteblocksForInstrument.put(orig, null); + continue; + } + newNoteblocksForInstrument.put(orig, noteblocksForInstrument.getOrDefault(instrumentMap.getOrDefault(orig, orig), new ArrayList<>())); } noteblocksForInstrument = newNoteblocksForInstrument; @@ -282,6 +295,12 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { ArrayList capturedNotes = new ArrayList<>(); for(Note note : song.uniqueNotes) { ArrayList availableBlocks = noteblocksForInstrument.get(note.instrument); + if(availableBlocks == null) { + // Note was mapped to "nothing". Pretend it got captured, but just ignore it + capturedNotes.add(note); + getNotes(note.instrument).put(note.note, null); + continue; + } BlockPos bestBlockPos = null; int bestBlockTuningSteps = Integer.MAX_VALUE; for(BlockPos blockPos : availableBlocks) { @@ -310,7 +329,9 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { HashMap missing = new HashMap<>(); for (Note note : missingNotes) { - Block block = Note.INSTRUMENT_BLOCKS.get(instrumentMap.getOrDefault(note.instrument, note.instrument)); + Instrument mappedInstrument = instrumentMap.getOrDefault(note.instrument, note.instrument); + if(mappedInstrument == null) continue; // Ignore if mapped to nothing + Block block = Note.INSTRUMENT_BLOCKS.get(mappedInstrument); Integer got = missing.get(block); if (got == null) got = 0; missing.put(block, got + 1); @@ -369,7 +390,14 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick { if(tuneInitialUntunedBlocks == -1 || tuneInitialUntunedBlocks < untunedNotes.size()) tuneInitialUntunedBlocks = untunedNotes.size(); - if(untunedNotes.isEmpty() && fullyTunedBlocks == song.uniqueNotes.size()) { + int existingUniqueNotesCount = 0; + for(Note n : song.uniqueNotes) { + if(noteBlocks.get(n.instrument).get(n.note) != null) + existingUniqueNotesCount++; + } + System.out.println("existingUniqueNotesCount = " + existingUniqueNotesCount); + + if(untunedNotes.isEmpty() && fullyTunedBlocks == existingUniqueNotesCount) { // Wait roundrip + 100ms before considering tuned after changing notes (in case the server rejects an interact) if(lastInteractAt == -1 || System.currentTimeMillis() - lastInteractAt >= ping * 2 + 100) { tuned = true;