Merge pull request #21 from EnderKill98/feature/bugfixes-and-improvements
Bugfixes and improvements
This commit is contained in:
commit
88800c055f
@ -9,6 +9,7 @@ import java.util.ArrayList;
|
|||||||
@me.shedaniel.autoconfig.annotation.Config.Gui.Background("textures/block/note_block.png")
|
@me.shedaniel.autoconfig.annotation.Config.Gui.Background("textures/block/note_block.png")
|
||||||
public class Config implements ConfigData {
|
public class Config implements ConfigData {
|
||||||
public boolean hideWarning;
|
public boolean hideWarning;
|
||||||
|
@ConfigEntry.Gui.Tooltip(count = 2) public boolean disableAsyncPlayback;
|
||||||
@ConfigEntry.Gui.Excluded @ConfigEntry.Gui.Tooltip(count = 2) public boolean monoNoteBlocks;
|
@ConfigEntry.Gui.Excluded @ConfigEntry.Gui.Tooltip(count = 2) public boolean monoNoteBlocks;
|
||||||
|
|
||||||
@ConfigEntry.Gui.Excluded
|
@ConfigEntry.Gui.Excluded
|
||||||
|
@ -5,19 +5,35 @@ import com.mojang.brigadier.arguments.FloatArgumentType;
|
|||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||||
|
import net.minecraft.block.enums.Instrument;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import semmiedev.disc_jockey.gui.screen.DiscJockeyScreen;
|
import semmiedev.disc_jockey.gui.screen.DiscJockeyScreen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
|
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
|
||||||
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
|
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
|
||||||
|
|
||||||
public class DiscjockeyCommand {
|
public class DiscjockeyCommand {
|
||||||
|
|
||||||
|
|
||||||
public static void register(CommandDispatcher<FabricClientCommandSource> commandDispatcher) {
|
public static void register(CommandDispatcher<FabricClientCommandSource> commandDispatcher) {
|
||||||
|
final ArrayList<String> instrumentNames = new ArrayList<>();
|
||||||
|
for (Instrument instrument : Instrument.values()) {
|
||||||
|
instrumentNames.add(instrument.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
final ArrayList<String> instrumentNamesAndAll = new ArrayList<>(instrumentNames);
|
||||||
|
instrumentNamesAndAll.add("all");
|
||||||
|
final ArrayList<String> instrumentNamesAndNothing = new ArrayList<>(instrumentNames);
|
||||||
|
instrumentNamesAndNothing.add("nothing");
|
||||||
|
|
||||||
commandDispatcher.register(
|
commandDispatcher.register(
|
||||||
literal("discjockey")
|
literal("discjockey")
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
@ -98,7 +114,130 @@ public class DiscjockeyCommand {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.then(literal("remapInstruments")
|
||||||
|
.executes(context -> {
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".instrument_info"));
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.then(literal("map")
|
||||||
|
.then(argument("originalInstrument", StringArgumentType.word())
|
||||||
|
.suggests((context, builder) -> CommandSource.suggestMatching(instrumentNamesAndAll, builder))
|
||||||
|
.then(argument("newInstrument", StringArgumentType.word())
|
||||||
|
.suggests((context, builder) -> CommandSource.suggestMatching(instrumentNamesAndNothing, builder))
|
||||||
|
.executes(context -> {
|
||||||
|
String originalInstrumentStr = StringArgumentType.getString(context, "originalInstrument");
|
||||||
|
String newInstrumentStr = StringArgumentType.getString(context, "newInstrument");
|
||||||
|
@Nullable Instrument originalInstrument = null, newInstrument = null;
|
||||||
|
for(Instrument maybeInstrument : Instrument.values()) {
|
||||||
|
if(maybeInstrument.toString().equalsIgnoreCase(originalInstrumentStr)) {
|
||||||
|
originalInstrument = maybeInstrument;
|
||||||
|
}
|
||||||
|
if(maybeInstrument.toString().equalsIgnoreCase(newInstrumentStr)) {
|
||||||
|
newInstrument = maybeInstrument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(originalInstrument == null && !originalInstrumentStr.equalsIgnoreCase("all")) {
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".invalid_instrument", originalInstrumentStr));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
Main.SONG_PLAYER.instrumentMap.put(instrument, newInstrument);
|
||||||
|
}
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".instrument_mapped_all", newInstrumentStr.toLowerCase()));
|
||||||
|
}else {
|
||||||
|
Main.SONG_PLAYER.instrumentMap.put(originalInstrument, newInstrument);
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".instrument_mapped", originalInstrumentStr.toLowerCase(), newInstrumentStr.toLowerCase()));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(literal("unmap")
|
||||||
|
.then(argument("instrument", StringArgumentType.word())
|
||||||
|
.suggests((context, builder) -> CommandSource.suggestMatching(instrumentNames, builder))
|
||||||
|
.executes(context -> {
|
||||||
|
String instrumentStr = StringArgumentType.getString(context, "instrument");
|
||||||
|
|
||||||
|
Instrument instrument = null;
|
||||||
|
for(Instrument maybeInstrument : Instrument.values()) {
|
||||||
|
if(maybeInstrument.toString().equalsIgnoreCase(instrumentStr)) {
|
||||||
|
instrument = maybeInstrument;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instrument == null) {
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".invalid_instrument", instrumentStr));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Main.SONG_PLAYER.instrumentMap.remove(instrument);
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".instrument_unmapped", instrumentStr.toLowerCase()));
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(literal("show")
|
||||||
|
.executes(context -> {
|
||||||
|
if(Main.SONG_PLAYER.instrumentMap.isEmpty()) {
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".no_mapped_instruments"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder maps = new StringBuilder();
|
||||||
|
for(Map.Entry<Instrument, Instrument> entry : Main.SONG_PLAYER.instrumentMap.entrySet()) {
|
||||||
|
if(maps.length() > 0) {
|
||||||
|
maps.append(", ");
|
||||||
|
}
|
||||||
|
maps
|
||||||
|
.append(entry.getKey().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;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(literal("clear")
|
||||||
|
.executes(context -> {
|
||||||
|
Main.SONG_PLAYER.instrumentMap.clear();
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".instrument_maps_cleared"));
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
.then(literal("loop")
|
||||||
|
.executes(context -> {
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".loop_status", Main.SONG_PLAYER.loopSong ? "yes" : "no"));
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
|
.then(literal("yes")
|
||||||
|
.executes(context -> {
|
||||||
|
Main.SONG_PLAYER.loopSong = true;
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".loop_enabled"));
|
||||||
|
return 1;
|
||||||
|
}))
|
||||||
|
.then(literal("no")
|
||||||
|
.executes(context -> {
|
||||||
|
Main.SONG_PLAYER.loopSong = false;
|
||||||
|
context.getSource().sendFeedback(Text.translatable(Main.MOD_ID + ".loop_disabled"));
|
||||||
|
return 1;
|
||||||
|
}))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import net.minecraft.util.hit.BlockHitResult;
|
|||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
import net.minecraft.world.GameMode;
|
import net.minecraft.world.GameMode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -60,13 +61,19 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
private int tuneInitialUntunedBlocks = -1;
|
private int tuneInitialUntunedBlocks = -1;
|
||||||
private HashMap<BlockPos, Pair<Integer, Long>> notePredictions = new HashMap<>();
|
private HashMap<BlockPos, Pair<Integer, Long>> notePredictions = new HashMap<>();
|
||||||
public boolean didSongReachEnd = false;
|
public boolean didSongReachEnd = false;
|
||||||
|
public boolean loopSong = false;
|
||||||
|
|
||||||
public SongPlayer() {
|
public SongPlayer() {
|
||||||
Main.TICK_LISTENERS.add(this);
|
Main.TICK_LISTENERS.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull HashMap<Instrument, Instrument> instrumentMap = new HashMap<>(); // Toy
|
public @NotNull HashMap<Instrument, @Nullable Instrument> instrumentMap = new HashMap<>(); // Toy
|
||||||
public synchronized void startPlaybackThread() {
|
public synchronized void startPlaybackThread() {
|
||||||
|
if(Main.config.disableAsyncPlayback) {
|
||||||
|
playbackThread = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.playbackThread = new Thread(() -> {
|
this.playbackThread = new Thread(() -> {
|
||||||
Thread ownThread = this.playbackThread;
|
Thread ownThread = this.playbackThread;
|
||||||
while(ownThread == this.playbackThread) {
|
while(ownThread == this.playbackThread) {
|
||||||
@ -150,7 +157,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
GameMode gameMode = client.interactionManager == null ? null : client.interactionManager.getCurrentGameMode();
|
GameMode gameMode = client.interactionManager == null ? null : client.interactionManager.getCurrentGameMode();
|
||||||
// In the best case, gameMode would only be queried in sync Ticks, no here
|
// In the best case, gameMode would only be queried in sync Ticks, no here
|
||||||
if (gameMode == null || !gameMode.isSurvivalLike()) {
|
if (gameMode == null || !gameMode.isSurvivalLike()) {
|
||||||
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.invalid_game_mode", gameMode.getTranslatableName()).formatted(Formatting.RED));
|
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.invalid_game_mode", gameMode == null ? "unknown" : gameMode.getTranslatableName()).formatted(Formatting.RED));
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -158,7 +165,12 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
long note = song.notes[index];
|
long note = song.notes[index];
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
if ((short)note <= Math.round(tick)) {
|
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)) {
|
if (!canInteractWith(client.player, blockPos)) {
|
||||||
stop();
|
stop();
|
||||||
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED));
|
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED));
|
||||||
@ -200,6 +212,9 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
if (index >= song.notes.length) {
|
if (index >= song.notes.length) {
|
||||||
stop();
|
stop();
|
||||||
didSongReachEnd = true;
|
didSongReachEnd = true;
|
||||||
|
if(loopSong) {
|
||||||
|
start(song);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -264,6 +279,13 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
if(!instrumentMap.isEmpty()) {
|
if(!instrumentMap.isEmpty()) {
|
||||||
HashMap<Instrument, ArrayList<BlockPos>> newNoteblocksForInstrument = new HashMap<>();
|
HashMap<Instrument, ArrayList<BlockPos>> newNoteblocksForInstrument = new HashMap<>();
|
||||||
for(Instrument orig : noteblocksForInstrument.keySet()) {
|
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<>()));
|
newNoteblocksForInstrument.put(orig, noteblocksForInstrument.getOrDefault(instrumentMap.getOrDefault(orig, orig), new ArrayList<>()));
|
||||||
}
|
}
|
||||||
noteblocksForInstrument = newNoteblocksForInstrument;
|
noteblocksForInstrument = newNoteblocksForInstrument;
|
||||||
@ -273,6 +295,12 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
ArrayList<Note> capturedNotes = new ArrayList<>();
|
ArrayList<Note> capturedNotes = new ArrayList<>();
|
||||||
for(Note note : song.uniqueNotes) {
|
for(Note note : song.uniqueNotes) {
|
||||||
ArrayList<BlockPos> availableBlocks = noteblocksForInstrument.get(note.instrument);
|
ArrayList<BlockPos> 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;
|
BlockPos bestBlockPos = null;
|
||||||
int bestBlockTuningSteps = Integer.MAX_VALUE;
|
int bestBlockTuningSteps = Integer.MAX_VALUE;
|
||||||
for(BlockPos blockPos : availableBlocks) {
|
for(BlockPos blockPos : availableBlocks) {
|
||||||
@ -301,7 +329,9 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
HashMap<Block, Integer> missing = new HashMap<>();
|
HashMap<Block, Integer> missing = new HashMap<>();
|
||||||
for (Note note : missingNotes) {
|
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);
|
Integer got = missing.get(block);
|
||||||
if (got == null) got = 0;
|
if (got == null) got = 0;
|
||||||
missing.put(block, got + 1);
|
missing.put(block, got + 1);
|
||||||
@ -322,7 +352,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(lastInteractAt != -1L) {
|
if(lastInteractAt != -1L) {
|
||||||
// Paper allows 8 interacts per 300 ms
|
// Paper allows 8 interacts per 300 ms (actually 9 it turns out, but lets keep it a bit lower anyway)
|
||||||
availableInteracts += ((System.currentTimeMillis() - lastInteractAt) / (310.0 / 8.0));
|
availableInteracts += ((System.currentTimeMillis() - lastInteractAt) / (310.0 / 8.0));
|
||||||
availableInteracts = Math.min(8f, Math.max(0f, availableInteracts));
|
availableInteracts = Math.min(8f, Math.max(0f, availableInteracts));
|
||||||
}else {
|
}else {
|
||||||
@ -360,7 +390,14 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
if(tuneInitialUntunedBlocks == -1 || tuneInitialUntunedBlocks < untunedNotes.size())
|
if(tuneInitialUntunedBlocks == -1 || tuneInitialUntunedBlocks < untunedNotes.size())
|
||||||
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)
|
// 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) {
|
if(lastInteractAt == -1 || System.currentTimeMillis() - lastInteractAt >= ping * 2 + 100) {
|
||||||
tuned = true;
|
tuned = true;
|
||||||
@ -417,6 +454,14 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
//client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(((float) (System.currentTimeMillis() % 2000)) * (360f/2000f), (1 - roughTuneProgress) * 180 - 90, true));
|
//client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(((float) (System.currentTimeMillis() % 2000)) * (360f/2000f), (1 - roughTuneProgress) * 180 - 90, true));
|
||||||
client.player.swingHand(Hand.MAIN_HAND);
|
client.player.swingHand(Hand.MAIN_HAND);
|
||||||
}
|
}
|
||||||
|
}else if((playbackThread == null || !playbackThread.isAlive()) && running && Main.config.disableAsyncPlayback) {
|
||||||
|
// Sync playback (off by default). Replacement for playback thread
|
||||||
|
try {
|
||||||
|
tickPlayback();
|
||||||
|
}catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,11 +23,25 @@
|
|||||||
"disc_jockey.info_tuning": "Tuning: (Speed: %s)",
|
"disc_jockey.info_tuning": "Tuning: (Speed: %s)",
|
||||||
"disc_jockey.info_playing": "Playing: [%s/%s] %s (Speed: %s)",
|
"disc_jockey.info_playing": "Playing: [%s/%s] %s (Speed: %s)",
|
||||||
"disc_jockey.info_finished": "Finished: %s (Speed: %s)",
|
"disc_jockey.info_finished": "Finished: %s (Speed: %s)",
|
||||||
|
"disc_jockey.instrument_info": "This maps instruments to be played by noteblocks for a different instrument instead.",
|
||||||
|
"disc_jockey.invalid_instrument": "Invalid instrument: %s",
|
||||||
|
"disc_jockey.instrument_mapped": "Mapped %s to %s",
|
||||||
|
"disc_jockey.instrument_mapped_all": "Mapped all instruments to %s",
|
||||||
|
"disc_jockey.instrument_unmapped": "Unmapped %s",
|
||||||
|
"disc_jockey.mapped_instruments": "Mapped instruments: %s",
|
||||||
|
"disc_jockey.no_mapped_instruments": "No instruments mapped, yet.",
|
||||||
|
"disc_jockey.instrument_maps_cleared": "Instrument mappings cleared.",
|
||||||
|
"disc_jockey.loop_status": "Loop song: %s",
|
||||||
|
"disc_jockey.loop_enabled": "Enabled looping of current song.",
|
||||||
|
"disc_jockey.loop_disabled": "Disabled looping of current song.",
|
||||||
"disc_jockey.warning": "WARNING!!! This mod is very likely to get false flagged as hacks, please contact a server administrator before using this mod! (You can disable this warning in the mod settings)",
|
"disc_jockey.warning": "WARNING!!! This mod is very likely to get false flagged as hacks, please contact a server administrator before using this mod! (You can disable this warning in the mod settings)",
|
||||||
"key.category.disc_jockey": "Disc Jockey",
|
"key.category.disc_jockey": "Disc Jockey",
|
||||||
"disc_jockey.key_bind.open_screen": "Open song selection screen",
|
"disc_jockey.key_bind.open_screen": "Open song selection screen",
|
||||||
"text.autoconfig.disc_jockey.title": "Disc Jockey",
|
"text.autoconfig.disc_jockey.title": "Disc Jockey",
|
||||||
"text.autoconfig.disc_jockey.option.hideWarning": "Hide Warning",
|
"text.autoconfig.disc_jockey.option.hideWarning": "Hide Warning",
|
||||||
|
"text.autoconfig.disc_jockey.option.disableAsyncPlayback": "Disable Async Playback",
|
||||||
|
"text.autoconfig.disc_jockey.option.disableAsyncPlayback.@Tooltip[0]": "Will force notes to play synchronously with client ticks instead of in a separate thread.",
|
||||||
|
"text.autoconfig.disc_jockey.option.disableAsyncPlayback.@Tooltip[1]": "This can lead to performance loss, especially when you client has low or inconsistent fps but can fix issues when playback does not happen at all.",
|
||||||
"text.autoconfig.disc_jockey.option.monoNoteBlocks": "Non-Directional Note Block Sounds",
|
"text.autoconfig.disc_jockey.option.monoNoteBlocks": "Non-Directional Note Block Sounds",
|
||||||
"text.autoconfig.disc_jockey.option.monoNoteBlocks.@Tooltip[0]": "Makes all note block sounds when playing a song non-directional, creating a more pleasurable listening experience (clientside)",
|
"text.autoconfig.disc_jockey.option.monoNoteBlocks.@Tooltip[0]": "Makes all note block sounds when playing a song non-directional, creating a more pleasurable listening experience (clientside)",
|
||||||
"text.autoconfig.disc_jockey.option.monoNoteBlocks.@Tooltip[1]": "If you don't know what that means, I recommend you just try it and hear the difference"
|
"text.autoconfig.disc_jockey.option.monoNoteBlocks.@Tooltip[1]": "If you don't know what that means, I recommend you just try it and hear the difference"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user